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

  1. Free disk space on the volume holding the upload directory (df -h, clean old run artifacts/logs).
  2. Check the server log entry upload.write_failed for the exact fs error (ENOSPC vs EACCES vs EIO).
  3. Verify the upload directory exists and is writable by the server process (permissions/ownership).
  4. 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

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


AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01). Data as JSON: /api/errors/7f316fb0b7888f37. Report an issue: GitHub.