{"record":{"id":"e0f59c35016c3a11","repo":"anomalyco/sst","slug":"tanstack-start-assets-directory-not-found-at-e0f59c","errorCode":null,"errorMessage":"TanStack Start assets directory not found at:\n  \"${path.resolve(assetsPath)}\".","messagePattern":"TanStack Start assets directory not found at:\n  \"(.+?)\"\\.","errorType":"validation","errorClass":"VisibleError","httpStatus":null,"severity":"error","filePath":"platform/src/components/cloudflare/tan-stack-start.ts","lineNumber":369,"sourceCode":"              server: toPlanPath(serverPath),\n              assets: toPlanPath(assetsPath),\n            };\n          }\n        }\n      }\n\n      async function resolveLegacyPlan() {\n        const serverPath = path.join(\n          outputPath,\n          \".output\",\n          \"server\",\n          \"index.mjs\",\n        );\n        const assetsPath = path.join(outputPath, \".output\", \"public\");\n\n        if (!(await existsAsync(serverPath))) return;\n        if (!(await existsAsync(assetsPath))) {\n          throw new VisibleError(\n            `TanStack Start assets directory not found at:\\n  \"${path.resolve(\n              assetsPath,\n            )}\".`,\n          );\n        }\n\n        return {\n          server: toPlanPath(serverPath),\n          assets: toPlanPath(assetsPath),\n        };\n      }\n\n      function toPlanPath(filePath: string) {\n        const relativePath = path.relative(outputPath, filePath);\n        return `./${relativePath.split(path.sep).join(\"/\")}`;\n      }\n    });\n  }","sourceCodeStart":351,"sourceCodeEnd":387,"githubUrl":"https://github.com/anomalyco/sst/blob/a0bd20f762883e72a35caccb4896c42ce5b3f707/platform/src/components/cloudflare/tan-stack-start.ts#L351-L387","documentation":"SST falls back to the legacy TanStack Start (Nitro) layout: `.output/server/index.mjs` plus `.output/public`. In this fallback, if the server bundle exists but `.output/public` does not, SST throws because the legacy layout is only partially present.","triggerScenarios":"A project emitting legacy `.output/server/index.mjs` without `.output/public`: Nitro/Nitro-based builds with prerendering disabled or public assets configured elsewhere, partial `.output` from an interrupted build.","commonSituations":"Older TanStack Start versions or custom Nitro presets producing server-only output; disabled static asset copying; stale partial `.output` left from a previous failed build.","solutions":["Migrate to the current Cloudflare adapter so the dist layout (`dist/server` + `dist/client`) is used","Ensure the legacy build copies public assets to `.output/public` (check Nitro `publicAssets`/prerender settings)","Clean `.output` and rebuild fully","If only static output is intended, use `sst.cloudflare.StaticSite`"],"exampleFix":"// before: .output/server/index.mjs exists, no .output/public\n// vite.config.ts\nexport default defineConfig({ ... })\n// after: enable public assets / upgrade adapter so dist/server + dist/client are emitted","handlingStrategy":"validation","validationCode":"import { existsSync } from 'fs';\nif (existsSync('apps/web/.output/server/index.mjs') && !existsSync('apps/web/.output/public'))\n  throw new Error('Legacy Nitro output missing .output/public; enable public assets or upgrade adapter');","typeGuard":null,"tryCatchPattern":"try {\n  await deploy();\n} catch (e) {\n  if (/assets directory not found/.test(e.message) && /\\.output/.test(e.message)) console.error('Legacy .output layout incomplete; rebuild with assets enabled');\n}","preventionTips":["Prefer the current Cloudflare adapter (dist layout) over the legacy .output layout","Ensure Nitro publicAssets/prerender settings copy public assets","Clean .output between builds","Verify .output/public exists before deploying legacy builds"],"tags":["tanstack-start","cloudflare","build-output","nitro","assets"],"backgroundTag":"build-output-not-found","analyzedSha":"a0bd20f762883e72a35caccb4896c42ce5b3f707","analyzedAt":"2026-08-30T11:26:00.383Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}