Skip to content

bug: Error: Anthropic API error during object generation: No object generated: response did not match schema #1300

@launchthatbrand

Description

@launchthatbrand

Description

When I try to use parse-prd via the MCP, i am getting error:

Error: Anthropic API error during object generation: No object generated: response did not match schema.
Version: 0.28.0
Name: task-master-ai
Current Tag: multifile-v2

If i create a very basic PRD, it seems to work fine. However on my typical larger 10 task PRD's, I am getting this error. I have been using Taskmaster for 1+ years, and never had this issue.

Example PRD that gives this error:
# MediaSync Multi-File Downloads PRD v2.0

## 1. Project Overview

Refactor the MediaSync plugin to support multiple files per download using a parent-child post type architecture inspired by Download Monitor. This enables users to attach multiple individual files, versions, and automatically process archives while maintaining a clean, scalable structure.

## 2. Executive Summary

Current MediaSync downloads are limited to one file per download. This PRD outlines a complete architectural overhaul using WordPress parent-child post types to enable multiple files, versioning, and archive support. The solution combines the best practices from Download Monitor with MediaSync's cloud storage capabilities.

## 3. Current State Analysis

PROBLEMS:
- Each ms_download post can only store ONE file
- No ability to group related files together
- Archive extraction creates complex manifest structure
- Difficult to manage file versions or updates
- No clear separation between download metadata and file data

LIMITATIONS:
- Single file URL and metadata per download
- Archive handling is a special case with custom JSON manifest
- No version tracking for file updates
- Frontend has separate logic for regular vs archive downloads

## 4. Proposed Architecture

### 4.1 Parent-Child Post Type Structure

TWO CUSTOM POST TYPES:

POST TYPE 1: ms_download (Parent)
- Purpose: Main download entity with metadata
- Contains: title, description, categories, tags, featured image
- Stores: download-level settings and statistics
- Relationship: Has many ms_download_file children

POST TYPE 2: ms_download_file (Child)
- Purpose: Individual file or file version
- Contains: file URL, cloud metadata, version info
- Stores: file-specific data and statistics
- Relationship: Belongs to one ms_download parent via post_parent field

### 4.2 Data Structure

PARENT DOWNLOAD (ms_download) META FIELDS:
- "_ms_download_is_archive" - Boolean flag for archive downloads
- "_ms_download_total_count" - Aggregated download count from all files
- "_ms_download_default_file" - ID of primary/default file to download
- "_ms_download_auto_version" - Boolean to enable auto-version naming

CHILD FILE (ms_download_file) META FIELDS:
- "_ms_file_url" - Cloud storage URL
- "_ms_file_name" - Original filename
- "_ms_file_size" - Size in bytes
- "_ms_cloud_file_id" - Cloud storage path/key
- "_ms_provider" - Cloud provider name (digitalocean, aws, gcp)
- "_ms_mime_type" - File MIME type
- "_ms_version" - Version string (1.0.0, v2, etc)
- "_ms_source" - Source type: "manual", "extracted", "archive_original"
- "_ms_source_archive_id" - Parent archive file ID if extracted
- "_ms_display_in_list" - Boolean to show/hide in frontend lists
- "_ms_display_order" - Integer for manual sorting
- "_ms_download_count" - Individual file download count
- "_ms_upload_date" - Upload timestamp
- "_ms_file_hash_md5" - MD5 hash for integrity
- "_ms_file_hash_sha256" - SHA256 hash for security
- "_ms_is_original_archive" - Boolean flag for original zip files

### 4.3 Archive Processing Workflow

WHEN USER UPLOADS A ZIP FILE:

STEP 1: Upload original zip to cloud storage
- Upload full zip file to DigitalOcean/AWS/GCP
- Store cloud URL and file ID

STEP 2: Create archive file record
- Insert new ms_download_file post
- Set post_parent to download ID
- Set meta: "_ms_is_original_archive" = true
- Set meta: "_ms_display_in_list" = false
- Store cloud URL and metadata

STEP 3: Extract files locally
- Extract all files from zip to temp directory
- Skip system files (MACOSX, .DS_Store, etc)
- Validate file types and sizes

STEP 4: Upload each extracted file
- Upload each file individually to cloud storage
- Generate unique cloud file IDs
- Calculate file sizes and hashes

STEP 5: Create file records for extracted files
- Insert ms_download_file post for each extracted file
- Set post_parent to download ID
- Set meta: "_ms_source" = "extracted"
- Set meta: "_ms_source_archive_id" = archive file ID
- Set meta: "_ms_display_in_list" = true
- Store all cloud metadata

STEP 6: Update parent download
- Set meta: "_ms_download_is_archive" = true
- Set meta: "_ms_download_total_count" = sum of all file counts
- Set meta: "_ms_download_default_file" = archive file ID for "Download All"

STEP 7: Cleanup
- Delete temporary extracted files
- Log extraction results
- Update admin UI to show all files

## 5. Admin UI Implementation

### 5.1 Download Edit Screen Structure

METABOX 1: Download Information (Sidebar)
- Location: Side column
- Priority: High
- Contains: Featured status, categories, tags, excerpt
- Same as current implementation

METABOX 2: Download Options (Sidebar)
- Location: Side column
- Priority: Default
- Contains: Access control, redirect settings, new tab option
- Same as current implementation

METABOX 3: Downloadable Files (Main Content)
- Location: Normal context
- Priority: High
- Contains: File repeater interface with version accordion UI
- NEW IMPLEMENTATION (inspired by Download Monitor)

### 5.2 File Repeater Interface Design

UPLOAD ZONE (when no files exist):
- Large drag-and-drop area
- Text: "Drag & Drop files here"
- Divider: "- or -"
- Buttons: "Upload File", "Media Library", "Custom URL", "Upload Archive"
- Shows upload progress bar when active
- Hides after first file is added

FILE LIST (collapsible accordions):
Each file displayed as accordion item:

ACCORDION HEADER (always visible):
- Drag handle icon (for reordering)
- File number (#1, #2, etc)
- File icon (based on MIME type)
- Filename
- File size (human readable)
- Version string (if set)
- Download count
- Delete button (trash icon)
- Expand/collapse chevron

ACCORDION CONTENT (expandable):
- File URL (read-only input, copy button)
- Cloud File ID (read-only)
- Provider badge (DigitalOcean/AWS/GCP)
- Version field (text input)
- Source indicator (Manual Upload / Extracted from Archive / Original Archive)
- If extracted: link to source archive
- Display in list toggle (checkbox)
- Upload date (read-only)
- File hashes (MD5, SHA256) - expandable section
- Replace file button
- Set as default download button

ADD MORE FILES SECTION (at bottom):
- Compact drag-drop zone
- Same upload buttons as initial zone
- Always visible for adding additional files

### 5.3 Archive Upload Special Handling

WHEN ZIP FILE IS DETECTED:
- Show modal dialog: "Archive Detected"
- Message: "This is an archive file. How would you like to handle it?"
- Option 1: "Extract and upload all files individually" (recommended)
- Option 2: "Keep as single archive file"
- Checkbox: "Keep original archive for 'Download All' button" (checked by default)
- Process button shows extraction progress

EXTRACTION PROGRESS MODAL:
- Title: "Extracting Archive..."
- Progress bar with file count
- Current file being processed
- Estimated time remaining
- Cancel button
- Success message with file count
- Auto-close after 3 seconds

POST-EXTRACTION UI:
- Archive file accordion marked with badge: "Original Archive"
- Extracted files marked with badge: "From Archive"
- Archive file accordion is collapsed by default
- Extracted files are expanded by default
- Link from extracted file to source archive

### 5.4 Drag-and-Drop Reordering

FUNCTIONALITY:
- Drag handle on left side of each accordion header
- Drag file up or down to reorder
- Visual placeholder shows drop position
- Auto-saves new order via AJAX
- Updates "_ms_display_order" meta for all affected files
- Smooth animations during drag

VISUAL FEEDBACK:
- Dragging file gets elevated shadow
- Drop zones highlighted with border
- Other files slide to make room
- Success notification after save

## 6. Backend Implementation

### 6.1 Post Type Registration

REGISTER ms_download POST TYPE:
- Labels: Download, Downloads, New Download, etc
- Public: true
- Has archive: true
- Supports: title, editor, thumbnail, excerpt, custom-fields
- Taxonomies: category, post_tag, custom taxonomies
- Menu icon: dashicons-download
- REST enabled: true
- GraphQL enabled: true (via WPGraphQL)

REGISTER ms_download_file POST TYPE:
- Labels: Download File, Download Files, etc
- Public: false (not directly accessible)
- Show in menu: false (accessed via parent)
- Supports: title, custom-fields
- Hierarchical: true (enables post_parent)
- REST enabled: true
- GraphQL enabled: true (via WPGraphQL)
- No archive page needed

### 6.2 Helper Functions

CREATE FILE MANAGEMENT FUNCTIONS:

FUNCTION: ms_add_file(download_id, file_data)
- Validates download_id exists
- Creates new ms_download_file post
- Sets post_parent to download_id
- Stores all file metadata
- Returns new file ID or WP_Error

FUNCTION: ms_remove_file(file_id, delete_cloud)
- Validates file_id exists
- Optionally deletes from cloud storage
- Removes all dependent files (if archive)
- Deletes file post
- Updates parent download counts
- Returns true or WP_Error

FUNCTION: ms_get_files(download_id, args)
- Retrieves all files for download
- Supports filtering by source, version, display_in_list
- Supports ordering by display_order, upload_date, name
- Returns array of file objects
- Includes all metadata

FUNCTION: ms_reorder_files(download_id, file_order_array)
- Validates all file IDs belong to download
- Updates "_ms_display_order" for each file
- Maintains consistent ordering
- Returns true or WP_Error

FUNCTION: ms_get_default_file(download_id)
- Gets "_ms_download_default_file" meta
- Falls back to first file if not set
- Returns file object or null

FUNCTION: ms_set_default_file(download_id, file_id)
- Validates file belongs to download
- Updates "_ms_download_default_file" meta
- Returns true or WP_Error

### 6.3 Archive Extractor Service

CREATE ZipExtractor CLASS MODIFICATIONS:

METHOD: process_archive(download_id, zip_file_path)
- Upload zip to cloud storage
- Create archive file record with "_ms_is_original_archive" = true
- Extract files to temporary directory
- Filter out system files
- Upload each file to cloud
- Create file record for each with "_ms_source" = "extracted"
- Link extracted files to archive via "_ms_source_archive_id"
- Update parent download "_ms_download_is_archive" = true
- Cleanup temporary files
- Return array of created file IDs

METHOD: validate_archive(file_path)
- Check file is valid zip
- Check compression ratio for zip bombs
- Validate total uncompressed size
- Check for malicious file types
- Return validation result

METHOD: upload_file_to_cloud(file_path, download_id, metadata)
- Use existing ProviderManager
- Generate unique cloud file ID
- Upload to configured provider
- Calculate file hash
- Return cloud URL and metadata

### 6.4 AJAX Upload Handler

ENDPOINT: wp_ajax_ms_upload_file
- Handles file uploads from admin UI
- Supports single file and multiple files
- Detects zip files and offers extraction
- Creates file records via ms_add_file()
- Returns JSON with file data for UI update

ENDPOINT: wp_ajax_ms_remove_file
- Validates file ownership
- Calls ms_remove_file()
- Returns success/error JSON

ENDPOINT: wp_ajax_ms_reorder_files
- Receives new file order array
- Calls ms_reorder_files()
- Returns success/error JSON

ENDPOINT: wp_ajax_ms_set_default_file
- Receives file_id
- Calls ms_set_default_file()
- Returns success/error JSON

### 6.5 Save Meta Box Handler

FUNCTION: save_files_meta_box(post_id, post)
- Verify nonce for security
- Check user permissions
- Loop through posted file data
- Update file post meta for each file
- Update parent download aggregated data
- Trigger file re-upload if URL changed
- Calculate new hashes if file replaced

## 7. GraphQL Schema

### 7.1 Download Type Extensions

EXTEND Download TYPE:
- isArchive: Boolean - Archive flag
- files: List of DownloadFile - All files
- displayedFiles: List of DownloadFile - Files with display_in_list = true
- defaultFile: DownloadFile - Primary download file
- originalArchiveFile: DownloadFile - Original zip if archive
- extractedFiles: List of DownloadFile - Files extracted from archive
- fileCount: Int - Total number of files
- totalDownloadCount: Int - Aggregated from all files

### 7.2 DownloadFile Type

CREATE NEW DownloadFile TYPE:
- id: ID - WordPress post ID
- databaseId: Int - Numeric ID
- title: String - File post title
- fileUrl: String - Cloud storage URL
- fileName: String - Original filename
- fileSize: Int - Size in bytes
- fileSizeFormatted: String - Human readable size
- cloudFileId: String - Cloud storage path
- provider: String - Provider name
- mimeType: String - MIME type
- version: String - Version string
- source: String - Source type
- sourceArchiveId: Int - Parent archive ID if extracted
- sourceArchiveFile: DownloadFile - Parent archive object
- isOriginalArchive: Boolean - Archive flag
- displayInList: Boolean - Display flag
- displayOrder: Int - Sort order
- downloadCount: Int - Individual download count
- uploadDate: String - Upload timestamp
- md5Hash: String - MD5 hash
- sha256Hash: String - SHA256 hash
- parent: Download - Parent download object

### 7.3 Query Fields

ADD QUERIES:
- downloadFile(id: ID, databaseId: Int): DownloadFile
- downloadFiles(where: DownloadFileQueryArgs): List of DownloadFile

QUERY ARGS:
- downloadId: Int - Filter by parent download
- source: String - Filter by source type
- displayInList: Boolean - Filter by display flag
- orderBy: Field and order

## 8. Frontend Implementation

### 8.1 React Component Updates

UPDATE DownloadCard COMPONENT:
- Check download.isArchive flag
- If archive: Show "Download All" button for originalArchiveFile
- If archive: Render ArchiveFolderView for displayedFiles
- If regular: Show single download button for defaultFile
- If regular with multiple files: Show file selector dropdown
- Display file count badge
- Show version info if available

UPDATE ArchiveFolderView COMPONENT:
- Accept files array from displayedFiles query
- Remove internal GraphQL query
- Display files in grid or list view
- Show file metadata (name, size, type, version)
- Individual download button per file
- "Download All" button for original archive
- Filter and search functionality
- Sort by name, size, date, version

CREATE NEW FileSelector COMPONENT:
- Dropdown list of available files
- Shows filename, version, size
- Default file pre-selected
- Download button triggers selected file
- Optional: Show all files in expanded view

### 8.2 GraphQL Query Updates

UPDATE GetDownloadBySlug QUERY:
Add to download fragment:
- isArchive
- fileCount
- totalDownloadCount
- defaultFile with all fields
- files with filter displayInList = true
- originalArchiveFile if isArchive = true

CREATE GetDownloadFiles QUERY:
Query downloadFiles by parent download ID
Include all file metadata
Support filtering and ordering
Pagination for large file lists

## 9. Migration Strategy

### 9.1 Existing Single-File Downloads

FOR EACH EXISTING ms_download POST:

STEP 1: Get current file metadata
- Read "_ms_download_file_url"
- Read "_ms_download_file_name"
- Read "_ms_download_file_size"
- Read "_ms_download_cloud_file_id"
- Read all other current meta fields

STEP 2: Create new ms_download_file post
- Insert post with parent = download_id
- Set title to filename
- Set post_status to "publish"

STEP 3: Migrate metadata to new file post
- Set "_ms_file_url" = old file_url
- Set "_ms_file_name" = old file_name
- Set "_ms_file_size" = old file_size
- Set "_ms_cloud_file_id" = old cloud_file_id
- Set "_ms_source" = "manual"
- Set "_ms_display_in_list" = true
- Set "_ms_display_order" = 0
- Set "_ms_upload_date" = post_date

STEP 4: Update parent download
- Set "_ms_download_default_file" = new file_id
- Keep old meta fields for backward compatibility
- Mark as migrated with "_ms_migrated_to_v2" = true

### 9.2 Existing Archive Downloads

FOR EACH ARCHIVE DOWNLOAD:

STEP 1: Get archive manifest
- Read "_ms_download_archive_manifest"
- Parse JSON to array
- Get "_ms_download_archive_base_url"

STEP 2: Create original archive file post
- Insert ms_download_file post
- Set "_ms_is_original_archive" = true
- Set "_ms_display_in_list" = false
- Set "_ms_file_url" = base_url + archive filename
- Store all archive metadata

STEP 3: Create file posts for each manifest entry
- Loop through manifest files
- Insert ms_download_file for each
- Set "_ms_source" = "extracted"
- Set "_ms_source_archive_id" = archive file_id
- Set "_ms_file_url" = manifest file URL
- Set "_ms_display_in_list" = true
- Copy all file metadata from manifest

STEP 4: Update parent download
- Ensure "_ms_download_is_archive" = true
- Set "_ms_download_default_file" = archive file_id
- Mark as migrated

### 9.3 Migration Command

CREATE WP-CLI COMMAND:
Command: wp mediasync migrate-to-v2
Options:
- --dry-run: Show what would be migrated without changes
- --batch-size: Number of posts per batch (default 50)
- --post-id: Migrate specific download only
- --force: Re-migrate even if already migrated

Output:
- Progress bar showing current/total
- Success count
- Error count with details
- Time elapsed
- Rollback instructions if needed

## 10. Storage Strategy

### 10.1 Cloud Storage Approach

KEEP BOTH ORIGINAL AND EXTRACTED:
- Original zip: Fast "Download All" option
- Extracted files: Individual file downloads
- Cost: Minimal (DigitalOcean Spaces: $5/month for 250GB)
- Benefit: Better UX, instant downloads, original preserved

DELETE OPTIONS:
- Admin setting: "Delete original archive after extraction"
- Admin setting: "Delete extracted files, keep archive only"
- Default: Keep both for best user experience

### 10.2 File Organization

CLOUD STORAGE STRUCTURE:
downloads/
  {download-id}/
    original-archive.zip (if kept)
    extracted/
      file1.pdf
      file2.jpg
      folder/
        file3.doc

BENEFITS:
- Clear organization by download
- Easy to identify which files belong together
- Simple cleanup when download deleted
- Supports nested folder structures from archives

## 11. Technical Constraints

WORDPRESS REQUIREMENTS:
- WordPress 6.0 or higher
- PHP 7.4 or higher
- MySQL 5.7 or higher

PLUGIN DEPENDENCIES:
- WPGraphQL plugin active
- WPGraphQL for Custom Post Types (optional)
- Existing MediaSync cloud storage configured

FILE LIMITATIONS:
- Maximum file size: Configurable (default 500MB)
- Supported archive formats: ZIP only (initially)
- Maximum files per download: Unlimited (practical limit ~1000)
- Maximum archive extraction size: Configurable (default 1GB uncompressed)

PERFORMANCE CONSIDERATIONS:
- Archive extraction runs via WordPress cron (async)
- File uploads chunked for large files
- GraphQL queries paginated for many files
- Database indexes on post_parent for fast file queries

## 12. Success Criteria

FUNCTIONALITY REQUIREMENTS:
1. Users can upload multiple individual files to one download
2. Uploading a zip auto-extracts and creates file records
3. Original zip preserved for "Download All" functionality
4. Admin UI is intuitive with drag-drop and visual feedback
5. All existing downloads migrate successfully without data loss
6. GraphQL queries work for both old and new structure
7. Frontend displays correctly in Regular and Archive modes
8. File reordering persists correctly
9. File deletion removes cloud files properly
10. Download statistics aggregate from all files

PERFORMANCE REQUIREMENTS:
- Admin UI loads in under 2 seconds with 100 files
- File upload completes in reasonable time based on size
- Archive extraction processes in background without blocking
- GraphQL queries return in under 500ms for typical downloads
- Migration completes at rate of 100 downloads per minute

USER EXPERIENCE REQUIREMENTS:
- Drag-drop works smoothly without lag
- Upload progress shows accurate percentage
- Extraction progress visible with cancel option
- Error messages are clear and actionable
- No data loss during migration
- Backward compatible with old download links

## 13. Future Enhancements (Out of Scope)

PHASE 2 FEATURES:
- Nested archive support (zip containing zips)
- File versioning with rollback capability
- File categories and tags within a download
- Bulk file operations (delete multiple, move to another download)
- File preview in admin (images, PDFs)
- Download analytics per file
- Scheduled file updates
- File access permissions per file
- S3-compatible storage for archives
- RAR and 7Z archive support

## 14. Implementation Timeline

ESTIMATED EFFORT:
- Week 1-2: Backend post type and meta field implementation
- Week 3-4: Admin UI development and AJAX handlers
- Week 5-6: Archive extraction and cloud upload logic
- Week 7-8: GraphQL schema and frontend components
- Week 9-10: Migration script and testing
- Week 11-12: Bug fixes, polish, and documentation

MILESTONE DELIVERABLES:
- Milestone 1: Post types registered, helper functions complete
- Milestone 2: Admin UI functional with file upload/delete
- Milestone 3: Archive extraction working end-to-end
- Milestone 4: GraphQL schema complete, frontend updated
- Milestone 5: Migration tested on staging with real data
- Milestone 6: Production release with rollback plan

## 15. Risk Mitigation

TECHNICAL RISKS:
- Risk: Archive extraction fails for large files
- Mitigation: Background processing, chunking, memory limits, timeout handling

- Risk: Migration corrupts existing data
- Mitigation: Dry-run mode, database backups, rollback script, phased rollout

- Risk: GraphQL breaking changes
- Mitigation: Maintain backward compatibility, deprecation warnings, versioned schema

OPERATIONAL RISKS:
- Risk: Cloud storage costs increase significantly
- Mitigation: Configurable retention policies, archive cleanup cron, usage monitoring

- Risk: Users confused by new UI
- Mitigation: Inline help text, video tutorials, migration guide, support documentation

## 16. Dependencies

REQUIRED BEFORE IMPLEMENTATION:
- Existing ZipExtractor service (wp-content/plugins/mediasync/includes/downloads/ZipExtractor.php)
- Existing ProviderManager (wp-content/plugins/mediasync/includes/core/ProviderManager.php)
- Existing DownloadAdmin (wp-content/plugins/mediasync/includes/admin/DownloadAdmin.php)
- Existing GraphQL integration (wp-content/plugins/mediasync/includes/downloads/DownloadFields.php)
- WPGraphQL plugin installed and activated

EXTERNAL DEPENDENCIES:
- WordPress Uploader (PlUpload) - Built into WordPress
- Cloud storage provider configured (DigitalOcean/AWS/GCP)
- PHP ZipArchive extension enabled
- Sufficient PHP memory limit (256MB recommended)
- WordPress cron enabled for background processing

Cursor eventually tried to run the MCP command 'models' and returns:

The issue persists. Let me check the models configuration to ensure the API keys are properly set:
{
"data": {
"activeModels": {
"main": {
"provider": "anthropic",
"modelId": "claude-3-7-sonnet-20250219",
"sweScore": 0.623,
"cost": {
"input": 3,
"output": 15
},
"keyStatus": {
"cli": true,
"mcp": false
}
},
"research": {
"provider": "perplexity",
"modelId": "sonar-pro",
"sweScore": null,
"cost": {
"input": 3,
"output": 15
},
"keyStatus": {
"mcp": false
}
},
"fallback": {
"provider": "anthropic",
"modelId": "claude-3-7-sonnet-20250219",
"sweScore": 0.623,
"cost": {
"input": 3,
"output": 15
},
"keyStatus": {
"cli": true,
"mcp": false
}
}
},
"message": "Successfully retrieved current model configuration"
},
"version": {
"version": "0.28.0",
"name": "task-master-ai"
},
"tag": {
"currentTag": "wordpress-blogs",
"availableTags": [
"master",
"wordpress-blogs",
"multi-file-downloads"
]
}
}
I can see the issue - the Anthropic API key is not configured for MCP (keyStatus.mcp is false). The parse_prd command requires AI processing and needs the API key to be available in the MCP environment.

However I have my anthropic key set in global .cursor/mcp.json file (global not project specific).

Cursor eventually switches to using the CLI via commands like:

task-master parse-prd .taskmaster/docs/mediasync-multifile-v2-prd.txt --num-tasks=5 --force

Which works, I assume because I have ANTHROPIC_API_KEY set in .env? However in Anthropic console it shows they are sent a 'Streaming' type and not the typical 'HTTP' type.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:mcpMCP server and integrationbugSomething isn't workingmedium-priorityImportant but not urgentprovider:anthropicAnthropic/Claude models

    Projects

    Status

    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions