agalwood/Motrix · error · MetadataError

plugin.metadata.value_not_serializable

plugin.metadata.value_not_serializable

Error message

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

What it means

The top-level value passed to the metadata set() path is strictly undefined. JSON.stringify would silently drop a top-level undefined (returning undefined), so serialize() short-circuits to an explicit, message-bearing error rather than storing nothing. This is the value===undefined branch, distinct from 113 (stringify threw) and 114 (stringify returned undefined).

Source

Thrown at src/core/plugin/capabilities/metadata.ts:68

  }
}

// ---------------------------------------------------------------------------
// Internal helpers
// ---------------------------------------------------------------------------

const DEFAULT_QUOTA = 64 << 10 // 64 KB

/**
 * Serialize `value` to JSON.
 * Throws `plugin.metadata.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 MetadataError(
      'plugin.metadata.value_not_serializable',
      'plugin.metadata.value_not_serializable: undefined is not JSON-serializable'
    )
  }
  let json: string | undefined
  try {
    json = JSON.stringify(value)
  } catch {
    throw new MetadataError(
      'plugin.metadata.value_not_serializable',
      'plugin.metadata.value_not_serializable: value cannot be serialized to JSON'
    )
  }
  if (json === undefined) {
    throw new MetadataError(
      'plugin.metadata.value_not_serializable',
      'plugin.metadata.value_not_serializable: value cannot be serialized to JSON'
    )

View on GitHub (pinned to 1a708ee577)

Solutions

  1. Use null (or an explicit empty marker) instead of undefined to represent absence.
  2. Skip the set() call entirely when the value is undefined.
  3. Default the value at the source with ?? null or ?? {}.

Example fix

// before
await metadata.set(taskId, pluginId, key, maybeValue)

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

Strategy: validation

Validate before calling

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

Type guard

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

Prevention

When it happens

Trigger: Calling metadata.set(taskId, pluginId, key, undefined); a variable that was conditionally assigned and ended up undefined; reading a missing config field and passing it straight through.

Common situations: Plugin stores the result of an optional lookup without checking; refactor left a placeholder; TypeScript optional property accessed without nullish-coalescing.

Related errors


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