{"record":{"id":"2058c5b7c86575b5","repo":"amruthpillai/reactive-resume","slug":"invalid-storage-key","errorCode":null,"errorMessage":"Invalid storage key","messagePattern":"Invalid storage key","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/api/src/features/storage/service.ts","lineNumber":220,"sourceCode":"\t\t\t\tmessage: \"Local filesystem storage is accessible and has read/write permission.\",\n\t\t\t};\n\t\t} catch (error: unknown) {\n\t\t\treturn {\n\t\t\t\ttype: \"local\",\n\t\t\t\tstatus: \"unhealthy\",\n\t\t\t\tmessage: \"Local filesystem storage is not accessible or lacks sufficient permissions.\",\n\t\t\t\terror: error instanceof Error ? error.message : \"Unknown error\",\n\t\t\t};\n\t\t}\n\t}\n\n\tprivate resolvePath(key: string): string {\n\t\tconst normalizedKey = key.replace(/^\\/*/, \"\");\n\t\tconst segments = normalizedKey\n\t\t\t.split(/[/\\\\]+/)\n\t\t\t.filter((segment) => segment.length > 0 && segment !== \".\" && segment !== \"..\");\n\n\t\tif (segments.length === 0) throw new Error(\"Invalid storage key\");\n\n\t\treturn join(this.rootDirectory, ...segments);\n\t}\n}\n\nclass S3StorageService implements StorageService {\n\tprivate readonly bucket: string;\n\tprivate readonly client: S3Client;\n\n\tconstructor() {\n\t\tif (!env.S3_ACCESS_KEY_ID || !env.S3_SECRET_ACCESS_KEY || !env.S3_BUCKET) {\n\t\t\tthrow new Error(\"S3 credentials are not set\");\n\t\t}\n\n\t\tthis.bucket = env.S3_BUCKET;\n\t\tthis.client = new S3Client({\n\t\t\tregion: env.S3_REGION,\n\t\t\tforcePathStyle: env.S3_FORCE_PATH_STYLE,","sourceCodeStart":202,"sourceCodeEnd":238,"githubUrl":"https://github.com/amruthpillai/reactive-resume/blob/3a5b12e2a40374a9571988701fcb75c5a1831c42/packages/api/src/features/storage/service.ts#L202-L238","documentation":"LocalStorageService.resolvePath throws when, after stripping leading slashes and filtering out empty/. /.. segments, no segments remain. This means the key resolves to the storage root itself and is rejected to prevent operating on the root directory. Generic Error (surfaces as 500).","triggerScenarios":"Passing an empty string key; a key of only slashes ('///'); a key composed solely of '.'/'..' segments; a key that normalized to nothing (e.g. all segments filtered).","commonSituations":"Bug in caller that builds the key from an undefined/blank variable; a code path that passes a prefix instead of a full key; an upstream normalize step that collapsed the key to empty.","solutions":["Validate the key is non-empty and contains at least one real path segment before calling storage methods.","Trace where the blank key originated — typically a missing field on the upload metadata or a default-empty config value.","Add a unit test on resolvePath for '', '/', '.', '..', '..' to lock in the contract.","If a legitimate operation targets a directory prefix (list), use list(prefix) which accepts a prefix, not write/read/delete with an empty key."],"exampleFix":"// before: passing an unvalidated key\nawait storage.write({ key: maybeBlank, data, contentType });\n// after: guard the key\nfunction safeKey(key: string): string {\n  const cleaned = key.replace(/^\\/+/, '').split(/[/\\\\]+/).filter(s => s && s !== '.' && s !== '..').join('/');\n  if (!cleaned) throw new TypeError('storage key must have at least one path segment');\n  return cleaned;\n}","handlingStrategy":"validation","validationCode":"function assertStorageKey(key: string): string {\n  const segs = key.replace(/^\\/+/, '').split(/[/\\\\]+/).filter(s => s && s !== '.' && s !== '..');\n  if (segs.length === 0) throw new TypeError('storage key must contain at least one segment');\n  return segs.join('/');\n}","typeGuard":"function isValidStorageKey(key: string): key is string {\n  return assertStorageKey.length > 0 && /[^./\\\\]/.test(key.replace(/^[./\\\\]+/, ''));\n}","tryCatchPattern":null,"preventionTips":["Validate keys at the call site, not just inside the storage layer.","Never pass a default-empty variable as a key.","Unit-test resolvePath against '', '/', '.', '..'."],"tags":["storage","validation","filesystem","path"],"backgroundTag":null,"analyzedSha":"3a5b12e2a40374a9571988701fcb75c5a1831c42","analyzedAt":"2026-08-12T22:31:22.666Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}