{"record":{"id":"c7e8ffc281785b4d","repo":"nexu-io/open-design","slug":"artifact-manifest-required","errorCode":"ARTIFACT_MANIFEST_REQUIRED","errorMessage":"artifactManifest is required for ${name}; no safe default manifest can be inferred","messagePattern":"artifactManifest is required for (.+?); no safe default manifest can be inferred","errorType":"error_code","errorClass":"ArtifactManifestRequiredError","httpStatus":null,"severity":"error","filePath":"apps/daemon/src/artifacts/create.ts","lineNumber":66,"sourceCode":"    encoding: input.encoding === 'base64' ? 'base64' : 'utf8',\n    artifact: true,\n    overwrite: false,\n    ...(input.artifactManifest === undefined ? {} : { artifactManifest: input.artifactManifest }),\n  };\n}\n\nexport function resolveCreateArtifactManifest(input: CreateProjectArtifactInput): unknown {\n  const manifest = input.artifactManifest !== undefined && input.artifactManifest !== null\n    ? input.artifactManifest\n    : inferLegacyManifest(input.name);\n  if (manifest) {\n    const validated = validateArtifactManifestInput(manifest, input.name);\n    if (!validated.ok) {\n      throw new ArtifactManifestInvalidError(validated.error);\n    }\n    return validated.value;\n  }\n  throw new ArtifactManifestRequiredError(input.name);\n}\n\nexport async function createProjectArtifactFile(options: CreateProjectArtifactOptions): Promise<unknown> {\n  const { input } = options;\n  const body = input.encoding === 'base64'\n    ? Buffer.from(input.content, 'base64')\n    : Buffer.from(input.content, 'utf8');\n  return await options.writeProjectFile(\n    options.projectsRoot,\n    options.projectId,\n    input.name,\n    body,\n    {\n      overwrite: false,\n      artifactManifest: resolveCreateArtifactManifest(input),\n    },\n    options.metadata,\n  );","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/apps/daemon/src/artifacts/create.ts#L48-L84","documentation":"Thrown by resolveCreateArtifactManifest() as ArtifactManifestRequiredError (code ARTIFACT_MANIFEST_REQUIRED) when no artifactManifest was supplied AND inferLegacyManifest() could not infer one from the file extension. Legacy inference only covers .html/.htm (html or deck), .md (markdown-document), and .svg (svg). Any other extension without an explicit manifest hits this.","triggerScenarios":"POST /api/projects/:id/files with artifact=true for a file whose name ends in something other than .html/.htm/.md/.svg (e.g. .json, .tsx, .png, no extension) and no artifactManifest in the body. Same path via `od artifacts create --name foo.json` without --manifest.","commonSituations":"Creating a react-component / mini-app / diagram / code-snippet / design-system artifact (none of which are inferable) and forgetting the manifest; renaming a file to a custom extension; creating an artifact with no extension.","solutions":["Provide an explicit artifactManifest in the request body (or via --manifest for the CLI).","Rename the file to .html/.htm/.md/.svg if you genuinely want the inferred manifest.","For react-component/mini-app/diagram/code-snippet/design-system kinds, always supply the manifest — inference does not cover them."],"exampleFix":"// before\nawait postCreateArtifactRequest({\n  baseUrl, projectId,\n  input: { name: 'widget.tsx', content, encoding: 'utf8' }\n});\n// after — explicit manifest for a react-component\nawait postCreateArtifactRequest({\n  baseUrl, projectId,\n  input: {\n    name: 'widget.tsx', content, encoding: 'utf8',\n    artifactManifest: {\n      kind: 'react-component',\n      renderer: 'react-component',\n      exports: ['jsx', 'zip']\n    }\n  }\n});","handlingStrategy":"validation","validationCode":"import { inferLegacyManifest } from './artifacts/manifest.js';\nconst needsExplicit = !inferLegacyManifest(name); // null for non-html/md/svg\nif (needsExplicit && !artifactManifest) {\n  throw new Error(`an explicit artifactManifest is required for ${name}`);\n}","typeGuard":"const INFERABLE_EXT = new Set(['.html', '.htm', '.md', '.svg']);\nfunction inferableFromName(name: string): boolean {\n  return INFERABLE_EXT.has(name.slice(name.lastIndexOf('.')).toLowerCase());\n}","tryCatchPattern":"try {\n  resolveCreateArtifactManifest(input);\n} catch (e) {\n  if (e instanceof ArtifactManifestRequiredError) {\n    // prompt user for a manifest, then retry\n  }\n  throw e;\n}","preventionTips":["Always pass an explicit artifactManifest for react-component, mini-app, diagram, code-snippet, and design-system kinds.","If relying on inference, keep the file extension as .html/.htm/.md/.svg.","Build the manifest upstream so the create call is deterministic."],"tags":["artifacts","manifest","validation","api","daemon"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}