toeverything/AFFiNE · error · OverCapacityError

Storage over capacity.

Error message

Storage over capacity.

What it means

During CloudBlobStorage.set(), if the server responds with a STORAGE_QUOTA_EXCEEDED error, it is rethrown as OverCapacityError('Storage over capacity.'). Unlike OverSizeError (per-file limit), this means the workspace's TOTAL storage allowance is exhausted — no file of any size can be uploaded until space is freed or the plan upgraded.

Source

Thrown at packages/common/nbstore/src/impls/cloud/blob.ts:211

          return;
        } catch {
          if (upload.uploadId) {
            await this.tryAbortMultipartUpload(
              blob.key,
              upload.uploadId,
              signal
            );
          }
          await this.uploadViaGraphql(blob, signal);
          return;
        }
      }

      await this.uploadViaGraphql(blob, signal);
    } catch (err) {
      const userFriendlyError = UserFriendlyError.fromAny(err);
      if (userFriendlyError.is('STORAGE_QUOTA_EXCEEDED')) {
        throw new OverCapacityError();
      }
      if (userFriendlyError.is('BLOB_QUOTA_EXCEEDED')) {
        throw new OverSizeError(this.humanReadableBlobSizeLimitCache);
      }
      if (userFriendlyError.is('CONTENT_TOO_LARGE')) {
        throw new OverSizeError(
          null,
          'Upload stopped by network proxy: file size exceeds the set limit.'
        );
      }
      throw err;
    }
  }

  override async delete(key: string, permanently: boolean) {
    await this.connection.gql({
      query: deleteBlobMutation,
      variables: { workspaceId: this.options.id, key, permanently },

View on GitHub (pinned to b4c8548c09)

Solutions

  1. Free workspace space: delete large/unneeded blobs and empty the trash (releaseDeletedBlobs) so quota is actually reclaimed.
  2. Upgrade the workspace plan / request a quota increase from the workspace owner.
  3. On self-hosted: raise the workspace storage quota in server config.
  4. Catch OverCapacityError in the UI and surface a clear 'storage full' action (upgrade/manage storage) instead of a generic failure.

Example fix

// before
try {
  await blobStorage.set(rec);
} catch (e) { toast('Upload failed'); }

// after
try {
  await blobStorage.set(rec);
} catch (e) {
  if (e instanceof OverCapacityError) {
    toast('Workspace storage is full — free space or upgrade your plan.');
  } else throw e;
}
Defensive patterns

Strategy: fallback

Validate before calling

// No reliable client pre-check for total quota; optionally surface current usage from
// workspace quota queries and warn before upload.

Type guard

import { OverCapacityError } from '@affine/nbstore/storage';
const isOverCapacity = (e: unknown): e is OverCapacityError => e instanceof OverCapacityError;

Try / catch

try { await blobStorage.set(rec); } catch (e) {
  if (e instanceof OverCapacityError) {
    await promptFreeSpaceOrUpgrade(); // delete unused blobs + releaseDeletedBlobs, or upgrade plan
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: Uploading any blob once the workspace's total quota (sum of stored blobs) is full; the per-file pre-check passed because the file itself is small, but the server rejects the createBlobUpload mutation with STORAGE_QUOTA_EXCEEDED.

Common situations: Free-tier workspace hitting its storage cap; team workspace shared quota consumed by other members; self-hosted deployment with a low AFFINE_QUOTA (total bytes) setting; deleted blobs still counted because trash was not released.

Related errors


AI-assisted analysis of toeverything/AFFiNE@b4c8548c09 (2026-08-18). Data as JSON: /api/errors/3d0727a8511119a9. Report an issue: GitHub.