abhigyanpatwari/GitNexus · error · BadRequestError
Uploaded folder has no usable name
Error message
Uploaded folder has no usable name
What it means
After multipart ingestion, the handler derives a filesystem-safe name from the upload's top-level folder via deriveUploadName, which sanitizes and returns null when the result is 'unknown', '.', '..', or starts with '.'. A null result becomes BadRequestError 400 'Uploaded folder has no usable name' — by design, so un-nameable folders are rejected instead of everyone colliding on UPLOAD_ROOT/unknown.
Source
Thrown at gitnexus/src/server/analyze-upload.ts:81
409,
);
}
export function createAnalyzeUploadHandler(deps: AnalyzeUploadDeps) {
const ingest = deps.ingest ?? ingestUpload;
return async function handleAnalyzeUploadRequest(req: Request, res: Response): Promise<void> {
let stageRoot: string | undefined;
let promotedDir: string | undefined;
let createdJobId: string | undefined;
let launched = false;
try {
const result = await ingest(req as IncomingMessage);
stageRoot = result.stageRoot;
const baseName = deriveUploadName(result.topLevelName);
if (!baseName) {
throw new BadRequestError('Uploaded folder has no usable name');
}
// webkitRelativePath prefixes every entry with the picked folder, so the
// real repo root is stageRoot/<topLevelName>. Validate it is a directory
// BEFORE taking the single analysis slot — a malformed (non-folder)
// upload must not be able to occupy the slot.
const innerRoot = path.join(result.stageRoot, result.topLevelName);
let innerIsDir = false;
try {
innerIsDir = (await fsp.stat(innerRoot)).isDirectory();
} catch {
innerIsDir = false;
}
if (!innerIsDir) {
throw new BadRequestError('Upload must be a folder');
}
const finalName = await pickAvailableName(baseName);View on GitHub (pinned to aac7515d2a)
Solutions
- Rename the folder to alphanumerics plus . _ - before uploading
- Avoid a leading dot in the folder name
- If the name contains spaces/unicode, transliterate or simplify it first
Example fix
# before folder name: '.hidden-config' -> 400 Uploaded folder has no usable name # after folder name: 'hidden-config' -> accepted
Defensive patterns
Strategy: validation
Validate before calling
const SAFE = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
function hasUsableFolderName(name) { return SAFE.test(name); }
// run before building the FormData
if (!hasUsableFolderName(topLevelName)) alertUser('Rename the folder to letters/numbers/._- without a leading dot'); Type guard
function isUploadableFolderName(name) {
return typeof name === 'string' && name.length > 0 && !name.startsWith('.') && /^[a-zA-Z0-9._-]+$/.test(name) && name !== 'unknown';
} Try / catch
try { await fetch('/api/analyze/upload', { method: 'POST', body: formData }); }
catch (e) {
if (e.status === 400 && /no usable name/.test(e.message)) promptUserToRenameFolder();
else throw e;
} Prevention
- Validate the picked folder name client-side before upload
- Warn on dot-prefix and punctuation/emoji-only folder names
- Default auto-generated names to a sanitized base plus unique suffix
When it happens
Trigger: POST /api/analyze/upload where the picked folder's name contains no characters from the safe set [A-Za-z0-9._-] after sanitization (e.g. '===', '***', emoji-only, whitespace-only), or is a dot-folder like '.config'.
Common situations: Uploading hidden/dot-prefixed directories from OS tools; folders named entirely in scripts/unicode that sanitizeRepoName strips to the 'unknown' sentinel; unusual browser-picker folder names.
Related errors
- Upload must be a folder
- Invalid upload path
- Upload path too long
- Upload path must not contain traversal segments
- Upload path escapes the sandbox
AI-assisted analysis of abhigyanpatwari/GitNexus@aac7515d2a (2026-08-20).
Data as JSON: /api/errors/36f506b0fb6f96ca.
Report an issue: GitHub.