agalwood/Motrix · error · StorageError

plugin.storage.value_not_serializable

plugin.storage.value_not_serializable

Error message

plugin.storage.value_not_serializable: undefined is not JSON-serializable

What it means

Storage capability mirror of 112. The top-level value passed to storage set() is undefined, and serialize() short-circuits with an explicit typed error rather than letting JSON.stringify silently drop it. Same value shape, different capability namespace (plugin.storage vs plugin.metadata).

Source

Thrown at src/core/plugin/capabilities/storage.ts:78

  constructor(
    public readonly code: string,
    message: string
  ) {
    super(message)
    this.name = 'StorageError'
  }
}

/**
 * Serialize `value` to JSON.
 * Throws `plugin.storage.value_not_serializable` when:
 *  - the value is top-level `undefined`
 *  - JSON.stringify returns undefined (e.g. a plain function)
 *  - JSON.stringify throws (e.g. BigInt, class with throwing toJSON)
 */
function serialize(value: unknown): string {
  if (value === undefined) {
    throw new StorageError(
      'plugin.storage.value_not_serializable',
      'plugin.storage.value_not_serializable: undefined is not JSON-serializable'
    )
  }
  let json: string | undefined
  try {
    json = JSON.stringify(value)
  } catch {
    throw new StorageError(
      'plugin.storage.value_not_serializable',
      'plugin.storage.value_not_serializable: value cannot be serialized to JSON'
    )
  }
  if (json === undefined) {
    throw new StorageError(
      'plugin.storage.value_not_serializable',
      'plugin.storage.value_not_serializable: value cannot be serialized to JSON'
    )

View on GitHub (pinned to 1a708ee577)

Solutions

  1. Use null to represent absence rather than undefined.
  2. Skip the set() call when the value is undefined.
  3. Default the value at the source with ?? null or ?? {}.

Example fix

// before
await storage.set(key, maybeValue)

// after
if (maybeValue !== undefined) await storage.set(key, maybeValue)
Defensive patterns

Strategy: validation

Validate before calling

if (value === undefined) throw new Error('storage value required')
await storage.set(key, value)

Type guard

function isDefined<T>(v: T | undefined): v is T { return v !== undefined }

Prevention

When it happens

Trigger: Calling storage.set(key, undefined); a variable that conditionally ended up undefined; refactor left a placeholder; plugin reads an optional env/config value and passes it through without a default.

Common situations: Plugin stores the result of an optional lookup; defaulting missing; TypeScript optional property accessed without nullish-coalescing.

Related errors


AI-assisted analysis of agalwood/Motrix@1a708ee577 (2026-08-12). Data as JSON: /api/errors/5f2158751fafae1c. Report an issue: GitHub.