agalwood/Motrix · error · TypeError

${callerName} reserved gid must contain exactly 16 hexadecim

Error message

${callerName} reserved gid must contain exactly 16 hexadecimal characters

What it means

`newEngineTaskId` mints an aria2 group-id (gid): exactly 16 hexadecimal characters. It prefers the injected `override` (used for deterministic tests/shells) and validates whatever that override returns, because a malformed gid would silently break the reservation-shield protocol in `TaskManager`. The `callerName` prefix in the message identifies which dispatch site produced the bad gid. This is a `TypeError`, not a `RangeError` — it indicates a programmer/test-config error, not bad input data.

Source

Thrown at src/core/lib/ids.ts:21

export function newTaskId(): string {
  return uuidv7()
}

/**
 * Mint a caller-reserved aria2 gid: exactly 16 hex characters (lowercase
 * when self-minted). Prefers the injected override (deterministic tests /
 * shells) and validates whatever it returns — a malformed reserved gid
 * would silently break the reservation-shield protocol in TaskManager.
 * `callerName` keeps each dispatch site's original error message.
 */
export function newEngineTaskId(
  override: (() => string) | undefined,
  callerName: string
): string {
  const gid = override?.() ?? randomBytes(8).toString('hex')
  if (!/^[0-9a-fA-F]{16}$/.test(gid)) {
    throw new TypeError(
      `${callerName} reserved gid must contain exactly 16 hexadecimal characters`
    )
  }
  return gid
}

View on GitHub (pinned to 1a708ee577)

Solutions

  1. Make the test override return `randomBytes(8).toString('hex')` or a literal 16-hex string like `'0123456789abcdef'`.
  2. Audit the override for off-by-one length or non-hex characters (uppercase hex is allowed by the regex).
  3. If you need a deterministic gid, derive it from a hex hash truncated/padded to 16 chars.
  4. Remove the override in production code paths — overrides are for tests only.

Example fix

// before
newEngineTaskId(() => 'abc123', 'TaskManager')  // 6 chars
// after
newEngineTaskId(() => '000000000000abc1', 'TaskManager')  // 16 hex chars
Defensive patterns

Strategy: type-guard

Validate before calling

function validateGid(gid: string): string {
  if (!/^[0-9a-fA-F]{16}$/.test(gid))
    throw new TypeError(`gid must be 16 hex chars, got: ${gid}`)
  return gid
}

Type guard

function isAria2Gid(v: unknown): v is string {
  return typeof v === 'string' && /^[0-9a-fA-F]{16}$/.test(v)
}

Try / catch

try {
  newEngineTaskId(override, callerName)
} catch (err) {
  if (err instanceof TypeError && err.message.endsWith('reserved gid must contain exactly 16 hexadecimal characters')) {
    newEngineTaskId(undefined, callerName)  // fall back to random
  } else throw err
}

Prevention

When it happens

Trigger: Providing an `override` whose return value is not 16 hex chars — e.g. a UUID (36 chars), an off-by-one fixture returning a 15-char gid, or a hand-built gid with a non-hex character. The random fallback (`randomBytes(8).toString('hex')`) always produces 16 lowercase hex, so production without an override never hits this.

Common situations: Test overrides that return a hardcoded gid of the wrong length; configuration injection supplying a UUID instead of an aria2 gid; copy-pasting a gid from a different engine.

Related errors


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