coleam00/Archon · critical
Failed to save uploaded file. Check available disk space.
Error message
Failed to save uploaded file. Check available disk space.
What it means
Returned when writing an uploaded file to the conversation's upload directory fails (writeErr caught). The server logs upload.write_failed with the error and conversationId, then responds 500 with this message directing the operator at disk space, since the most common cause of an fs write failure during upload is an exhausted or failing filesystem.
Source
Thrown at packages/server/src/routes/api.ts:2389
path: filePath,
name: safeName || fileId,
mimeType: normalizedMime,
size: entry.size,
});
}
} catch (writeErr: unknown) {
for (const f of savedFiles) {
await unlink(f.path).catch((err: NodeJS.ErrnoException) => {
if (err.code !== 'ENOENT') {
getLog().warn({ err, filePath: f.path, conversationId }, 'upload.rollback_failed');
}
});
}
getLog().error({ err: writeErr, conversationId }, 'upload.write_failed');
return {
ok: false,
status: 500,
error: 'Failed to save uploaded file. Check available disk space.',
};
}
return { ok: true, savedFiles, uploadDir };
}
async function dispatchToOrchestrator(
conversationId: string,
message: string,
extraContext?: Omit<HandleMessageContext, 'isolationHints'>,
filesToCleanup?: { files: AttachedFile[]; uploadDir: string }
): Promise<{ accepted: boolean; status: string }> {
const result = await lockManager.acquireLock(conversationId, async () => {
// Emit lock:true at handler start so the UI knows processing has begun.
// Fire-and-forget — if no SSE stream is connected yet, the event is buffered.
webAdapter.emitLockEvent(conversationId, true);
try {
await handleMessage(webAdapter, conversationId, message, {View on GitHub (pinned to 0773b97458)
Solutions
- Free disk space on the volume holding the upload directory (df -h, clean old run artifacts/logs).
- Check the server log entry upload.write_failed for the exact fs error (ENOSPC vs EACCES vs EIO).
- Verify the upload directory exists and is writable by the server process (permissions/ownership).
- Retry the upload once space/permissions are fixed.
Example fix
// before: blind retry after failure
await upload(file); // 500
// after: check capacity first
const stat = fs.statfsSync(uploadRoot);
if (stat.bavail * stat.bsize < file.size * 2) throw new Error('Insufficient disk space');
await upload(file); Defensive patterns
Strategy: validation
Validate before calling
import { statfsSync } from 'node:fs';
function hasSpaceFor(dir: string, bytes: number): boolean {
const s = statfsSync(dir);
return s.bavail * s.bsize > bytes * 2; // headroom factor
}
if (!hasSpaceFor(uploadDir, file.size)) throw new Error('Insufficient disk space for upload'); Type guard
function isUploadSaveFailure(res: { status: number; error?: string }): res is { status: 500; error: 'Failed to save uploaded file. Check available disk space.' } {
return res.status === 500 && /Failed to save uploaded file/.test(res.error ?? '');
} Try / catch
try {
await uploadFile(convId, file);
} catch (err) {
if (isUploadSaveFailure(err)) {
// do not blind-retry; free space / fix permissions first
const free = statfsSync(uploadDir).bavail * statfsSync(uploadDir).bsize;
throw new Error(`Upload write failed; ${free} bytes free on upload volume`, { cause: err });
}
throw err;
} Prevention
- Alert on disk usage for the volume holding Archon run artifacts and upload dirs (e.g. >80%).
- Prune old run artifacts/logs on a schedule so uploads never hit a full disk.
- Verify upload directory ownership/permissions after any manual maintenance.
- Check the upload.write_failed log entry to distinguish ENOSPC from EACCES/EIO before fixing.
When it happens
Trigger: POSTing multipart uploads to the conversation message route when the write of a file to the conversation uploadDir fails: disk full, inode exhaustion, permission denied on the upload directory, quota exceeded, or I/O error on the backing device.
Common situations: Self-hosted instance running on a small volume that filled up with run artifacts/logs; Docker container hitting a disk quota; read-only remount after disk errors; upload dir owned by a different user after a manual fix.
Related errors
- tar extraction failed (exit ${exitCode}): ${details}
- Failed to move extracted web UI from ${tmpDir} to ${targetDi
- ENOENT
- EACCES
- Failed to read version: ${err.message}
AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01).
Data as JSON: /api/errors/7f316fb0b7888f37.
Report an issue: GitHub.