{"record":{"id":"605624b3b36f3e13","repo":"agalwood/Motrix","slug":"label-is-not-an-integer","errorCode":null,"errorMessage":"${label} is not an integer","messagePattern":"(.+?) is not an integer","errorType":"validation","errorClass":"RangeError","httpStatus":null,"severity":"error","filePath":"src/core/lib/sqlite-integers.ts","lineNumber":14,"sourceCode":"/**\n * Conversions between better-sqlite3 `safeIntegers()` rows and JavaScript\n * numbers, shared by the SQLite-backed stores.\n */\n\nexport function safeIntegerFromSql(value: unknown, label: string): number {\n  if (typeof value === 'number') {\n    if (!Number.isSafeInteger(value)) {\n      throw new RangeError(`${label} exceeds the JavaScript safe integer range`)\n    }\n    return value\n  }\n  if (typeof value !== 'bigint') {\n    throw new RangeError(`${label} is not an integer`)\n  }\n  if (\n    value < BigInt(Number.MIN_SAFE_INTEGER) ||\n    value > BigInt(Number.MAX_SAFE_INTEGER)\n  ) {\n    throw new RangeError(`${label} exceeds the JavaScript safe integer range`)\n  }\n  return Number(value)\n}\n\nexport function nonNegativeIntegerFromBigInt(\n  value: bigint,\n  label: string\n): number {\n  const converted = safeIntegerFromSql(value, label)\n  if (converted < 0) {\n    throw new RangeError(`${label} must be non-negative`)\n  }","sourceCodeStart":1,"sourceCodeEnd":32,"githubUrl":"https://github.com/agalwood/Motrix/blob/1a708ee57746c434e2c67a44bbf0906a976afea4/src/core/lib/sqlite-integers.ts#L1-L32","documentation":"Thrown by safeIntegerFromSql when a value read from a better-sqlite3 row is neither a number nor a bigint. The function exists to bridge SQLite safeIntegers() rows (which arrive as bigint) with JavaScript numbers; anything else means the column did not store an integer at all (e.g. text, null, blob, float). The label argument identifies which field failed so the message names the offending column.","triggerScenarios":"Calling safeIntegerFromSql(value, label) where value is a string, null, undefined, boolean, or object — i.e. a SQLite cell that was not declared/stored as INTEGER, or a NULL that was not coalesced before the call. Common when a schema migration left a column as TEXT or when a JOIN returns an unexpected NULL.","commonSituations":"Schema drift where a column type changed from INTEGER to TEXT; queries that SELECT an expression/alias whose SQLite affinity yields TEXT; nullable foreign-key columns that return NULL; loading a fixture or seed file whose numeric fields were quoted.","solutions":["Check the SQLite schema (PRAGMA table_info) for the named column and ensure it has INTEGER affinity.","Coalesce NULLs in the query (SELECT COALESCE(col, 0)) or guard before calling safeIntegerFromSql.","If the column legitimately holds non-integer data, parse it explicitly (Number(row.col)) instead of routing through safeIntegerFromSql.","Re-run the failing query in the sqlite3 CLI and inspect typeof() of the offending cell to confirm its storage class."],"exampleFix":"// before\nconst id = safeIntegerFromSql(row.maybeNullId, 'maybeNullId')\n// after\nconst id = safeIntegerFromSql(row.maybeNullId ?? 0, 'maybeNullId')","handlingStrategy":"validation","validationCode":"function isSqliteIntegerLike(value: unknown): value is number | bigint {\n  return typeof value === 'bigint' || (typeof value === 'number' && Number.isInteger(value))\n}\n// before calling safeIntegerFromSql:\nif (!isSqliteIntegerLike(row.col)) {\n  throw new Error(`column 'col' is not an integer; got ${typeof row.col}`)\n}","typeGuard":"function isSqliteIntegerLike(value: unknown): value is number | bigint {\n  return typeof value === 'bigint' || (typeof value === 'number' && Number.isInteger(value))\n}","tryCatchPattern":"try {\n  const id = safeIntegerFromSql(row.col, 'col')\n} catch (e) {\n  if (e instanceof RangeError && /is not an integer/.test(e.message)) {\n    // handle non-integer cell\n  } else throw e\n}","preventionTips":["Run PRAGMA table_info on every column passed to these helpers during schema migrations to confirm INTEGER affinity.","Coalesce nullable columns in the SQL (COALESCE(col, 0)) rather than relying on runtime guards.","Add a typed wrapper around your db.prepare statements that returns the column type, so the compiler flags mismatches."],"tags":["sqlite","type-coercion","data-integrity"],"backgroundTag":null,"analyzedSha":"1a708ee57746c434e2c67a44bbf0906a976afea4","analyzedAt":"2026-08-12T16:18:09.346Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}