{"record":{"id":"3d0727a8511119a9","repo":"toeverything/AFFiNE","slug":"storage-over-capacity","errorCode":null,"errorMessage":"Storage over capacity.","messagePattern":"Storage over capacity\\.","errorType":"exception","errorClass":"OverCapacityError","httpStatus":null,"severity":"error","filePath":"packages/common/nbstore/src/impls/cloud/blob.ts","lineNumber":211,"sourceCode":"          return;\n        } catch {\n          if (upload.uploadId) {\n            await this.tryAbortMultipartUpload(\n              blob.key,\n              upload.uploadId,\n              signal\n            );\n          }\n          await this.uploadViaGraphql(blob, signal);\n          return;\n        }\n      }\n\n      await this.uploadViaGraphql(blob, signal);\n    } catch (err) {\n      const userFriendlyError = UserFriendlyError.fromAny(err);\n      if (userFriendlyError.is('STORAGE_QUOTA_EXCEEDED')) {\n        throw new OverCapacityError();\n      }\n      if (userFriendlyError.is('BLOB_QUOTA_EXCEEDED')) {\n        throw new OverSizeError(this.humanReadableBlobSizeLimitCache);\n      }\n      if (userFriendlyError.is('CONTENT_TOO_LARGE')) {\n        throw new OverSizeError(\n          null,\n          'Upload stopped by network proxy: file size exceeds the set limit.'\n        );\n      }\n      throw err;\n    }\n  }\n\n  override async delete(key: string, permanently: boolean) {\n    await this.connection.gql({\n      query: deleteBlobMutation,\n      variables: { workspaceId: this.options.id, key, permanently },","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/b4c8548c09da21b2898443559a5b846f0ccf5dd8/packages/common/nbstore/src/impls/cloud/blob.ts#L193-L229","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Free workspace space: delete large/unneeded blobs and empty the trash (releaseDeletedBlobs) so quota is actually reclaimed.","Upgrade the workspace plan / request a quota increase from the workspace owner.","On self-hosted: raise the workspace storage quota in server config.","Catch OverCapacityError in the UI and surface a clear 'storage full' action (upgrade/manage storage) instead of a generic failure."],"exampleFix":"// before\ntry {\n  await blobStorage.set(rec);\n} catch (e) { toast('Upload failed'); }\n\n// after\ntry {\n  await blobStorage.set(rec);\n} catch (e) {\n  if (e instanceof OverCapacityError) {\n    toast('Workspace storage is full — free space or upgrade your plan.');\n  } else throw e;\n}","handlingStrategy":"fallback","validationCode":"// No reliable client pre-check for total quota; optionally surface current usage from\n// workspace quota queries and warn before upload.","typeGuard":"import { OverCapacityError } from '@affine/nbstore/storage';\nconst isOverCapacity = (e: unknown): e is OverCapacityError => e instanceof OverCapacityError;","tryCatchPattern":"try { await blobStorage.set(rec); } catch (e) {\n  if (e instanceof OverCapacityError) {\n    await promptFreeSpaceOrUpgrade(); // delete unused blobs + releaseDeletedBlobs, or upgrade plan\n    return;\n  }\n  throw e;\n}","preventionTips":["Free space and release deleted blobs when nearing quota","Surface quota usage in storage-management UI before users hit the wall","Distinguish OverCapacityError (workspace full) from OverSizeError (file too big) in UX"],"tags":["blob-storage","quota","upload","affine"],"backgroundTag":"storage-quota-exceeded","analyzedSha":"b4c8548c09da21b2898443559a5b846f0ccf5dd8","analyzedAt":"2026-08-18T21:16:52.546Z","contentChangedAt":"2026-08-18T21:16:52.546Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}