danny-avila/LibreChat · error
Unexpected batch upload response: ${JSON.stringify(result).s
Error message
Unexpected batch upload response: ${JSON.stringify(result).slice(0, 200)} What it means
Thrown by batchUploadCodeEnvFiles (Code/crud.js) when the codeapi POST /upload/batch response is structurally invalid: missing storage_session_id, missing files array, or not an object. This is a contract-mismatch guard, not a per-file failure.
Source
Thrown at api/server/services/Files/Code/crud.js:255
},
httpAgent: codeServerHttpAgent,
httpsAgent: codeServerHttpsAgent,
timeout: 120000,
maxContentLength: MAX_FILE_SIZE,
maxBodyLength: MAX_FILE_SIZE,
};
const response = await axios.post(`${baseURL}/upload/batch`, form, options);
/** @type {{ message: string; storage_session_id: string; files: Array<{ status: string; fileId?: string; filename: string; error?: string }>; succeeded: number; failed: number }} */
const result = response.data;
if (
!result ||
typeof result !== 'object' ||
!result.storage_session_id ||
!Array.isArray(result.files)
) {
throw new Error(`Unexpected batch upload response: ${JSON.stringify(result).slice(0, 200)}`);
}
if (result.message === 'error') {
throw new Error('All files in batch upload failed');
}
if (result.failed > 0) {
const failedNames = result.files
.filter((f) => f.status === 'error')
.map((f) => `${f.filename}: ${f.error || 'unknown'}`)
.join(', ');
logger.warn(`[batchUploadCodeEnvFiles] ${result.failed} file(s) failed: ${failedNames}`);
}
const successFiles = result.files
.filter((f) => f.status === 'success' && f.fileId)
.map((f) => ({ fileId: f.fileId, filename: f.filename }));
return { storage_session_id: result.storage_session_id, files: successFiles };View on GitHub (pinned to 5ff282f900)
Solutions
- Capture the first 200 chars of the response (the error message already truncates to 200) to see what codeapi actually returned.
- Confirm the code server version supports the /upload/batch endpoint and its documented response shape.
- Check for an intercepting proxy (nginx, ingress) that may have returned an HTML error page.
- Fall back to per-file uploads if the batch endpoint is unavailable on this deployment.
Defensive patterns
Strategy: fallback
Type guard
/** @param {unknown} r * @returns {r is { storage_session_id: string; files: unknown[] }} */
function isBatchUploadResponse(r) {
return !!r && typeof r === 'object' && typeof r.storage_session_id === 'string' && Array.isArray(r.files);
} Try / catch
try {
await batchUploadCodeEnvFiles(params);
} catch (err) {
if (/Unexpected batch upload response/.test(err.message)) {
// fall back to per-file uploads
return Promise.all(files.map((f) => uploadCodeEnvFile({ ...params, file: f })));
}
throw err;
} Prevention
- Type-guard the batch response before consuming it.
- Fall back to per-file uploads when the batch endpoint is unavailable or returns a foreign shape.
- Keep codeapi version in sync with the documented batch response contract.
When it happens
Trigger: codeapi returns a response that breaks the documented `{ message, storage_session_id, files[], succeeded, failed }` shape — e.g. an HTML error page parsed as a string, a 2xx with an error body, or a newer/older API version with a different schema.
Common situations: Code server version skew (response schema changed); code server behind a reverse proxy returning an HTML 502; auth passed but the batch endpoint isn't enabled on this build.
Related errors
- Error uploading file: ${result.message}
- All files in batch upload failed
- Error uploading code environment file: ${error.message}
- Image validation failed for ${file.filename}: ${validation.e
- No file_id provided
AI-assisted analysis of danny-avila/LibreChat@5ff282f900 (2026-08-12).
Data as JSON: /api/errors/bc3155c235ea69eb.
Report an issue: GitHub.