{"record":{"id":"b881b002294a3864","repo":"clockworklabs/SpacetimeDB","slug":"failed-to-canonicalize-path","errorCode":null,"errorMessage":"Failed to canonicalize path {}: {}","messagePattern":"Failed to canonicalize path (.+?): (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/cli/build.rs","lineNumber":376,"sourceCode":"                file_path.display(),\n            )\n        });\n        if file_type.is_dir() {\n            ls_recursively(&file_path, repo_root, out);\n        } else {\n            out.push(make_repo_root_relative(&file_path, repo_root));\n        }\n    }\n}\n\n/// Treat `relative_path` as a relative path within the repo root's templates directory\n/// and transform it into an absolute, canonical path.\nfn get_full_path_within_manifest_dir(relative_path: &Path, _manifest_dir: &Path) -> PathBuf {\n    let repo_root = get_repo_root();\n    let full_path = repo_root.join(\"templates\").join(relative_path);\n\n    full_path.canonicalize().unwrap_or_else(|e| {\n        panic!(\"Failed to canonicalize path {}: {}\", full_path.display(), e);\n    })\n}\n\n/// Transform `full_path` into a relative path within `repo_root`.\n///\n/// `full_path` and `repo_root` should both be canonical paths, as by [`Path::canonicalize`].\nfn make_repo_root_relative(full_path: &Path, repo_root: &Path) -> PathBuf {\n    full_path\n        .strip_prefix(repo_root)\n        .map(|p| p.to_path_buf())\n        .unwrap_or_else(|_| {\n            panic!(\n                \"Path {} is outside repo root {}\",\n                full_path.display(),\n                repo_root.display()\n            )\n        })\n}","sourceCodeStart":358,"sourceCodeEnd":394,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/6dee26c6efc2856793e12b148a59742964f5d783/crates/cli/build.rs#L358-L394","documentation":"Build-time panic in crates/cli/build.rs: canonicalizing `{repo_root}/templates/{relative_path}` failed in `get_full_path_within_manifest_dir`. Every template referenced from templates-list.json is resolved to an absolute canonical path before listing its files; canonicalize fails when that path doesn't exist (dangling component), so this fires when the list references a template directory that is absent on disk.","triggerScenarios":"templates/templates-list.json contains an entry whose directory field has no matching folder under templates/ (typo, renamed folder, not yet created); the templates directory was excluded from the build context; case-sensitivity mismatch between the JSON entry and the folder name.","commonSituations":"Editing the JSON list before creating the folder; sparse checkouts or Docker contexts omitting templates subdirectories; developing on case-insensitive macOS then building on case-sensitive Linux.","solutions":["Compare the panic's path against disk: `ls <printed-path>`; create the directory or fix the JSON entry.","Validate every entry resolves: `jq -r '.templates[].directory' templates/templates-list.json | while read d; do test -d \"templates/$d\" || echo \"missing: $d\"; done`.","Ensure the build context includes the whole templates/ tree.","Check exact casing of folder names when building on case-sensitive filesystems."],"exampleFix":"# before: templates-list.json says directory \"chat-console\" but disk has \"chat-console-rs\"\n# after: fix the entry\njq 'map(if .directory == \"chat-console\" then .directory = \"chat-console-rs\" else . end)' templates/templates-list.json","handlingStrategy":"validation","validationCode":"# Validate all template list entries resolve before building:\njq -r '.templates[].directory' templates/templates-list.json | while read -r d; do\n  realpath -e \"templates/$d\" >/dev/null 2>&1 || echo \"unresolvable: templates/$d\"\ndone","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Create the template directory and its files before adding the JSON entry.","Match folder-name casing exactly, especially when moving from macOS to Linux builds.","CI-validate the JSON list against the filesystem on every PR."],"tags":["spacetimedb","build-script","path-canonicalization","templates","directory-not-found"],"backgroundTag":"path-canonicalization-failed","analyzedSha":"6dee26c6efc2856793e12b148a59742964f5d783","analyzedAt":"2026-08-20T06:08:37.179Z","contentChangedAt":"2026-08-20T06:08:37.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}