{"record":{"id":"c53353499742ac45","repo":"Budibase/budibase","slug":"unsupported-project-doc-path-relpath","errorCode":null,"errorMessage":"Unsupported Project doc path '${relPath}'.","messagePattern":"Unsupported Project doc path '(.+?)'\\.","errorType":"http","errorClass":"HTTPError","httpStatus":400,"severity":"error","filePath":"packages/server/src/sdk/workspace/projects/backups/imports.ts","lineNumber":312,"sourceCode":"    }\n  } catch (err) {\n    throw validationError || new HTTPError(\"Project package is invalid.\", 400)\n  }\n}\n\nconst getResourceTypeForDocPath = (\n  tmpPath: string,\n  filePath: string\n): ResourceType => {\n  const relPath = relative(tmpPath, filePath)\n  const pathParts = relPath.split(/[\\\\/]/)\n  const [docsDirectory, resourceType] = pathParts\n  if (\n    docsDirectory !== PROJECT_DOCS_DIRECTORY ||\n    pathParts.length !== 3 ||\n    !relPath.endsWith(\".json\")\n  ) {\n    throw new HTTPError(`Unsupported Project doc path '${relPath}'.`, 400)\n  }\n  if (\n    !resourceType ||\n    !ALLOWED_IMPORT_TYPES.has(resourceType as ResourceType)\n  ) {\n    throw new HTTPError(`Unsupported Project doc path '${relPath}'.`, 400)\n  }\n  return resourceType as ResourceType\n}\n\nconst RESOURCE_ID_PREFIXES: Record<ResourceType, string[]> = {\n  [ResourceType.PROJECT]: [prefixed(DocumentType.PROJECT)],\n  [ResourceType.AGENT]: [prefixed(DocumentType.AGENT)],\n  [ResourceType.DATASOURCE]: [\n    prefixed(DocumentType.DATASOURCE),\n    prefixed(DocumentType.DATASOURCE_PLUS),\n  ],\n  [ResourceType.TABLE]: [prefixed(DocumentType.TABLE)],","sourceCodeStart":294,"sourceCodeEnd":330,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/sdk/workspace/projects/backups/imports.ts#L294-L330","documentation":"getResourceTypeForDocPath maps each doc path inside the package (e.g. <docsDirectory>/<resourceType>/<id>.json) to a resource type. If the first path segment is not the expected PROJECT_DOCS_DIRECTORY, the path does not have exactly 3 segments, or the file lacks a .json extension, this HTTPError (400) is thrown.","triggerScenarios":"A tar entry inside the package whose path doesn't conform to `<docs-dir>/<resourceType>/<docId>.json` — wrong top-level directory name, nested subdirectories (4+ segments), loose files at the root, or non-JSON files such as .txt, .lock or binary assets.","commonSituations":"Hand-crafted or tool-modified packages that rename the docs folder; extra metadata files (README, .DS_Store) packed into the archive; packages produced by an older/newer export format than the server supports; archives that wrapped files in an extra parent folder.","solutions":["Inspect the archive with `tar -tzf project.tar.gz` and confirm paths match `<docsDirectory>/<resourceType>/<id>.json` exactly (check PROJECT_DOCS_DIRECTORY constant in imports.ts for the expected name).","Remove non-doc files (README, .DS_Store, dotfiles, assets) from the archive or move them outside the docs directory.","Re-export the project from a compatible Budibase version rather than hand-assembling the package.","If the archive has an extra wrapping folder, repackage so the docs directory is at the archive root."],"exampleFix":"// before: paths like\n//   my-app/documents/tables/ta_x.json  (wrong dir + extra nesting)\n//   notes.txt\n// after:\n//   documents/tables/ta_x.json\n//   documents/screens/screen_x.json\ntar -czf project.tar.gz documents/","handlingStrategy":"validation","validationCode":"const PROJECT_DOCS_DIRECTORY = \"documents\" // check imports.ts for the actual constant\n\nfunction validateDocPathShape(entryPath: string): boolean {\n  const parts = entryPath.split(/[\\\\/]/)\n  return (\n    parts[0] === PROJECT_DOCS_DIRECTORY &&\n    parts.length === 3 &&\n    parts[2].endsWith(\".json\")\n  )\n}","typeGuard":null,"tryCatchPattern":"try {\n  await api.importProjectPackage(file)\n} catch (err) {\n  if (err?.status === 400 && err.message.startsWith(\"Unsupported Project doc path\")) {\n    // inspect `tar -tzf` output; fix directory layout / remove non-JSON files\n  } else throw err\n}","preventionTips":["Inspect `tar -tzf project.tar.gz` before upload and verify every path matches <docsDir>/<type>/<id>.json","Exclude dotfiles and metadata (.DS_Store, README) from packages","Never hand-rename the top-level docs directory","Use matching exporter/importer Budibase versions"],"tags":["http-400","path-validation","import","schema-mismatch"],"backgroundTag":"unsupported-package-layout","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}