agalwood/Motrix · error · StorageError
plugin.storage.quota_exceeded
plugin.storage.quota_exceeded
Error message
plugin.storage.quota_exceeded: projected usage ${projected} exceeds quota ${this.quotaBytes} What it means
Thrown by assertQuota() before any write when the projected total bytes for that plugin would exceed quotaBytes (default 5 MB, override via constructor). The projection subtracts the existing size of the same key (so re-writing the same key with a smaller/equal value does not double-count) and adds the incoming value's UTF-8 byte length. It is a pre-flight guard, so the row is never partially written.
Source
Thrown at src/core/plugin/capabilities/storage.ts:144
projectedSize: number
): void {
const row = this.db
.prepare<[string], { total: number }>(
'SELECT COALESCE(SUM(size), 0) AS total FROM plugin_storage WHERE plugin_id = ?'
)
.get(pluginId) ?? { total: 0 }
const currentRow = this.db
.prepare<[string, string], { size: number } | undefined>(
'SELECT size FROM plugin_storage WHERE plugin_id = ? AND key = ?'
)
.get(pluginId, key)
const currentSize = currentRow?.size ?? 0
const projected = row.total - currentSize + projectedSize
if (projected > this.quotaBytes) {
throw new StorageError(
'plugin.storage.quota_exceeded',
`plugin.storage.quota_exceeded: projected usage ${projected} exceeds quota ${this.quotaBytes}`
)
}
}
// -------------------------------------------------------------------------
// get
// -------------------------------------------------------------------------
async get(pluginId: string, key: string): Promise<StorageGetResult> {
const row = this.db
.prepare<
[string, string],
{ value: string; version: number } | undefined
>(
'SELECT value, version FROM plugin_storage WHERE plugin_id = ? AND key = ?'
)View on GitHub (pinned to 1a708ee577)
Solutions
- Reduce the value size — compress, downsample, or trim the structure before storing.
- Delete or overwrite old keys (host.delete / host.keys + cleanup loop) to bring the running total down before writing the new key.
- If the plugin legitimately needs more space, construct StorageCapabilityHost with a larger quotaBytes: new StorageCapabilityHost({ db, quotaBytes: 20 << 20 }).
- Split one large value across multiple plugins only if the data model genuinely shards; otherwise prefer trimming.
Example fix
// before
const host = new StorageCapabilityHost({ db })
await host.set(pluginId, 'log', bigLogString)
// after
const host = new StorageCapabilityHost({ db, quotaBytes: 20 << 20 })
await host.set(pluginId, 'log', bigLogString.slice(0, 2_000_000)) Defensive patterns
Strategy: validation
Validate before calling
const totalBytes = (await host.keys(pluginId)).reduce(async (acc, k) => acc + (await host.get(pluginId, k))?.__size ?? 0, 0)
// simpler: pre-check incoming size
if (Buffer.byteLength(JSON.stringify(value) ?? '', 'utf8') + approxCurrentTotal > QUOTA) { /* trim first */ } Try / catch
try { await host.set(pluginId, key, value) }
catch (e) { if (e.code === 'plugin.storage.quota_exceeded') { await cleanupOldKeys(pluginId); await host.set(pluginId, key, value) } else throw e } Prevention
- Track approximate per-plugin usage and prune before writes.
- Avoid storing unbounded histories; cap list lengths.
- Raise quotaBytes at host construction for data-heavy plugins.
When it happens
Trigger: host.set or host.compareAndSet where (currentTotalBytes - existingSizeForKey + newSize) > quotaBytes. Concretely: writing many keys whose SUM(size) passes 5 MB, replacing a small key with a much larger value that crosses the threshold, or writing a single multi-MB blob.
Common situations: A plugin accumulates unbounded history/cache rows over time and eventually crosses 5 MB; a plugin stores large base64 blobs or serialized images; the default quota was not raised for a data-heavy plugin. Note the check is per-pluginId, not per-key, so many small keys add up.
Related errors
- plugin.metadata.quota_exceeded
- plugin.storage.cas_mismatch
- PLUGIN_ACTIVATION_CAP_EXCEEDED
- timer_quota_exceeded
- plugin.commands.id_out_of_namespace
AI-assisted analysis of agalwood/Motrix@1a708ee577 (2026-08-12).
Data as JSON: /api/errors/7add4a413d976325.
Report an issue: GitHub.