{"record":{"id":"d6f004f39a15475d","repo":"nexu-io/open-design","slug":"could-not-deploy-referenced-files-parts-join","errorCode":null,"errorMessage":"Could not deploy referenced files (${parts.join('; ')}).","messagePattern":"Could not deploy referenced files \\((.+?)\\)\\.","errorType":"http","errorClass":"DeployError","httpStatus":400,"severity":"error","filePath":"apps/daemon/src/deploy.ts","lineNumber":349,"sourceCode":"    });\n  }\n\n  return {\n    entryPath,\n    html,\n    files: Array.from(files.values()),\n    missing,\n    invalid,\n  };\n}\n\nexport async function buildDeployFileSet(projectsRoot: string, projectId: string, entryName: string, options: DeployOptions = {}) {\n  const plan = await buildDeployFilePlan(projectsRoot, projectId, entryName, options);\n  if (plan.missing.length || plan.invalid.length) {\n    const parts = [];\n    if (plan.missing.length) parts.push(`missing: ${plan.missing.join(', ')}`);\n    if (plan.invalid.length) parts.push(`invalid: ${plan.invalid.join(', ')}`);\n    throw new DeployError(`Could not deploy referenced files (${parts.join('; ')}).`, 400, {\n      missing: plan.missing,\n      invalid: plan.invalid,\n    });\n  }\n  return plan.files;\n}\n\nasync function addVisibleProjectFilesToDeployPlan(\n  files: Map<string, DeployFile>,\n  input: { projectsRoot: string; projectId: string; metadata?: unknown },\n) {\n  if (isLinkedFolderProject(input.metadata)) return;\n  const projectFiles = await listFiles(input.projectsRoot, input.projectId, { metadata: input.metadata });\n  for (const item of projectFiles) {\n    if (!item?.name || files.has(item.name)) continue;\n    const safePath = validateProjectPath(item.name);\n    // The selected entry is already mapped to provider-root index.html. Keep\n    // the original root index reserved so choosing index-v1.html does not get","sourceCodeStart":331,"sourceCodeEnd":367,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/apps/daemon/src/deploy.ts#L331-L367","documentation":"Thrown by buildDeployFileSet in apps/daemon/src/deploy.ts:349 as `DeployError('Could not deploy referenced files (...).', 400, { missing, invalid })`. buildDeployFileSet calls buildDeployFilePlan and, unlike the plan step (which intentionally returns missing/invalid without throwing), refuses to produce an uploadable file set when the entry HTML references assets that are missing on disk or resolve to invalid (out-of-scope/blocked) paths. The interpolated parts list distinguishes `missing:` and `invalid:` references, and the details object carries the raw arrays.","triggerScenarios":"The entry HTML's `<link>`, `<script src>`, `<img src>`, or other references point to files that don't exist in the project (populating `plan.missing`) or that `validateProjectPath` rejects as outside the sandbox / otherwise invalid (populating `plan.invalid`), and buildDeployFileSet is then called.","commonSituations":"Assets were deleted or moved after the HTML was generated; absolute or `../` references that escape the project directory; references to files filtered out by the deploy file allowlist; case-sensitivity mismatch on a case-sensitive filesystem; linked folder project referencing external paths.","solutions":["Inspect the returned `details.missing` and `details.invalid` arrays to get the exact broken references.","Restore or re-export the missing assets so every reference in the entry HTML resolves under the project directory.","Rewrite references that escape the project (remove leading `/` or `../`) so they resolve relative to the entry.","If using a linked folder project, ensure referenced files live under `metadata.baseDir`."],"exampleFix":"// before\n<!-- index.html -->\n<link rel=\"stylesheet\" href=\"/assets/style.css\"> <!-- missing/invalid -->\n\n// after\n<link rel=\"stylesheet\" href=\"assets/style.css\"> <!-- relative, exists in project -->","handlingStrategy":"validation","validationCode":"// Call the non-throwing plan first, surface missing/invalid to the user.\nconst plan = await buildDeployFilePlan(root, id, entryName, opts);\nif (plan.missing.length || plan.invalid.length) {\n  return res.status(400).json({\n    error: 'Fix referenced files before deploying.',\n    missing: plan.missing,\n    invalid: plan.invalid,\n  });\n}\nconst files = await buildDeployFileSet(root, id, entryName, opts);","typeGuard":"function hasReferenceIssues(plan: DeployFilePlan): boolean {\n  return plan.missing.length > 0 || plan.invalid.length > 0;\n}","tryCatchPattern":"try {\n  files = await buildDeployFileSet(root, id, entryName, opts);\n} catch (err) {\n  if (err instanceof DeployError && err.details && (err.details.missing || err.details.invalid)) {\n    return res.status(400).json({\n      error: err.message,\n      missing: err.details.missing,\n      invalid: err.details.invalid,\n    });\n  }\n  throw err;\n}","preventionTips":["Use buildDeployFilePlan (non-throwing) before buildDeployFileSet to gather issues without a thrown error.","Re-export artifacts to regenerate references right before deploying.","Keep all referenced assets under the project directory and use relative paths."],"tags":["deploy","validation","assets","references"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}