amruthpillai/reactive-resume · error · Error
Invalid storage key
Error message
Invalid storage key
What it means
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).
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.
Example fix
// before: passing an unvalidated key
await storage.write({ key: maybeBlank, data, contentType });
// after: guard the key
function safeKey(key: string): string {
const cleaned = key.replace(/^\/+/, '').split(/[/\\]+/).filter(s => s && s !== '.' && s !== '..').join('/');
if (!cleaned) throw new TypeError('storage key must have at least one path segment');
return cleaned;
} Defensive patterns
Strategy: validation
Validate before calling
function assertStorageKey(key: string): string {
const segs = key.replace(/^\/+/, '').split(/[/\\]+/).filter(s => s && s !== '.' && s !== '..');
if (segs.length === 0) throw new TypeError('storage key must contain at least one segment');
return segs.join('/');
} Type guard
function isValidStorageKey(key: string): key is string {
return assertStorageKey.length > 0 && /[^./\\]/.test(key.replace(/^[./\\]+/, ''));
} Prevention
- 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 '', '/', '.', '..'.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- Private storage writes are not supported by the local…
- A compound selector can contain only one type selector.
- Application document cannot be empty.
- Application documents must be PDF files.
- Attribute is not available on .
AI-assisted analysis of amruthpillai/reactive-resume@3a5b12e2a4 (2026-08-12).
Data as JSON: /api/errors/2058c5b7c86575b5.
Report an issue: GitHub.
Appendix: source
Thrown at packages/api/src/features/storage/service.ts:220
message: "Local filesystem storage is accessible and has read/write permission.",
};
} catch (error: unknown) {
return {
type: "local",
status: "unhealthy",
message: "Local filesystem storage is not accessible or lacks sufficient permissions.",
error: error instanceof Error ? error.message : "Unknown error",
};
}
}
private resolvePath(key: string): string {
const normalizedKey = key.replace(/^\/*/, "");
const segments = normalizedKey
.split(/[/\\]+/)
.filter((segment) => segment.length > 0 && segment !== "." && segment !== "..");
if (segments.length === 0) throw new Error("Invalid storage key");
return join(this.rootDirectory, ...segments);
}
}
class S3StorageService implements StorageService {
private readonly bucket: string;
private readonly client: S3Client;
constructor() {
if (!env.S3_ACCESS_KEY_ID || !env.S3_SECRET_ACCESS_KEY || !env.S3_BUCKET) {
throw new Error("S3 credentials are not set");
}
this.bucket = env.S3_BUCKET;
this.client = new S3Client({
region: env.S3_REGION,
forcePathStyle: env.S3_FORCE_PATH_STYLE,View on GitHub (pinned to 3a5b12e2a4)