{"record":{"id":"ff37d4c99fbe891d","repo":"remotion-dev/remotion","slug":"assetpath-must-be-a-non-empty-public-folder-path","errorCode":null,"errorMessage":"assetPath must be a non-empty public-folder path, or an asset must be selected in Studio.","messagePattern":"assetPath must be a non-empty public-folder path, or an asset must be selected in Studio\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/studio/src/components/WebMcp.tsx","lineNumber":176,"sourceCode":"\tassetPath,\n\tcurrentContent,\n\tstaticFiles,\n}: {\n\treadonly assetPath: unknown;\n\treadonly currentContent: {\n\t\treadonly asset?: string;\n\t\treadonly type: string;\n\t} | null;\n\treadonly staticFiles: readonly {readonly name: string}[];\n}) => {\n\tconst resolvedAssetPath =\n\t\tassetPath === undefined\n\t\t\t? currentContent?.type === 'asset'\n\t\t\t\t? (currentContent.asset ?? null)\n\t\t\t\t: null\n\t\t\t: assetPath;\n\tif (typeof resolvedAssetPath !== 'string' || resolvedAssetPath.length === 0) {\n\t\tthrow new Error(\n\t\t\t'assetPath must be a non-empty public-folder path, or an asset must be selected in Studio.',\n\t\t);\n\t}\n\n\tif (!staticFiles.some((file) => file.name === resolvedAssetPath)) {\n\t\tthrow new Error(`Asset ${resolvedAssetPath} was not found in public/.`);\n\t}\n\n\treturn resolvedAssetPath;\n};\n\nexport const WebMcp: FC = () => {\n\tconst {addCaptionJob, addVideoMattingJob} = useContext(RenderQueueContext);\n\tconst staticFiles = useStaticFiles();\n\tconst {canSelect, clearSelection, selectedItems, selectItems} =\n\t\tuseTimelineSelection();\n\tconst {canvasContent, compositions, currentCompositionMetadata, folders} =\n\t\tuseContext(Internals.CompositionManager);","sourceCodeStart":158,"sourceCodeEnd":194,"githubUrl":"https://github.com/remotion-dev/remotion/blob/b2f4e34732f3c6c222ea029413e22dc402218cd7/packages/studio/src/components/WebMcp.tsx#L158-L194","documentation":"The WebMcp asset tool resolves the asset path from the explicit assetPath argument or the currently selected Studio content. If neither yields a non-empty string, it throws because it cannot determine which public-folder asset to operate on.","triggerScenarios":"Calling the WebMcp asset tool with assetPath omitted while no asset is selected in Studio, or passing assetPath: '' / non-string.","commonSituations":"MCP agent calls the tool without arguments expecting the selection to provide context; Studio opened without selecting an asset; a script sending an empty string path.","solutions":["Pass an explicit non-empty assetPath pointing at a file in public/ (e.g. 'audio/voice.mp3').","Select the desired asset in Remotion Studio before invoking the tool.","Double-check the argument spelling — assetPath, not src or path.","List static files first to pick a valid public-folder path."],"exampleFix":"// before\nawait tool.execute({}); // no selection\n// after\nawait tool.execute({assetPath: 'audio/voice.mp3'});","handlingStrategy":"type-guard","validationCode":"if (typeof assetPath !== 'string' || assetPath.length === 0) {\n  throw new Error('assetPath is required when no asset is selected.');\n}","typeGuard":"const hasAssetPath = (a: unknown): a is string =>\n  typeof a === 'string' && a.length > 0;","tryCatchPattern":"try {\n  const p = resolveAssetPath(input);\n} catch (e) {\n  if (e.message.includes('assetPath must be a non-empty')) {\n    return 'No asset selected — pass assetPath explicitly.';\n  }\n}","preventionTips":["Always pass assetPath explicitly from tooling.","Select an asset in Studio before invoking selection-less calls.","Validate non-empty string inputs before tool calls."],"tags":["mcp","validation","studio"],"backgroundTag":"missing-required-argument","analyzedSha":"b2f4e34732f3c6c222ea029413e22dc402218cd7","analyzedAt":"2026-09-09T13:27:51.281Z","contentChangedAt":"2026-09-09T13:27:51.281Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}