{"record":{"id":"2e7f5dd765a603c5","repo":"decolua/9router","slug":"machineid-is-required","errorCode":null,"errorMessage":"machineId is required","messagePattern":"machineId is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/lib/db/repos/apiKeysRepo.js","lineNumber":29,"sourceCode":"    isActive: row.isActive === 1 || row.isActive === true,\n    createdAt: row.createdAt,\n  };\n}\n\nexport async function getApiKeys() {\n  const db = await getAdapter();\n  const rows = db.all(`SELECT * FROM apiKeys ORDER BY createdAt ASC`);\n  return rows.map(rowToKey);\n}\n\nexport async function getApiKeyById(id) {\n  const db = await getAdapter();\n  const row = db.get(`SELECT * FROM apiKeys WHERE id = ?`, [id]);\n  return rowToKey(row);\n}\n\nexport async function createApiKey(name, machineId) {\n  if (!machineId) throw new Error(\"machineId is required\");\n  const db = await getAdapter();\n  const { generateApiKeyWithMachine } = await import(\"@/shared/utils/apiKey\");\n  const result = generateApiKeyWithMachine(machineId);\n  const apiKey = {\n    id: uuidv4(),\n    name,\n    key: result.key,\n    machineId,\n    isActive: true,\n    createdAt: new Date().toISOString(),\n  };\n  db.run(\n    `INSERT INTO apiKeys(id, key, name, machineId, isActive, createdAt) VALUES(?, ?, ?, ?, ?, ?)`,\n    [apiKey.id, apiKey.key, apiKey.name, apiKey.machineId, 1, apiKey.createdAt]\n  );\n  return apiKey;\n}\n","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/src/lib/db/repos/apiKeysRepo.js#L11-L47","documentation":"createApiKey generates API keys that embed the machine id (generateApiKeyWithMachine), so the key is bound to a specific installation. It refuses to run without a machineId, because a machine-less key would be unverifiable at request-validation time.","triggerScenarios":"Calling createApiKey(name) with one argument, or createApiKey(name, null/undefined/\"\") — typically from code that hasn't loaded the machine id yet or passes an unset env/config value.","commonSituations":"Bootstrap/setup scripts running before MACHINE_ID is initialized; API route handlers reading machineId from a request body the client didn't send; fresh installs where the machine-id file hasn't been created yet.","solutions":["Pass the machine id explicitly: createApiKey(name, await getMachineId()) using the app's machine-id helper.","If machineId comes from a request body, validate it is a non-empty string before calling and return a 400 to the client otherwise.","Ensure the machine id has been generated/initialized (start the app once so ~/.9router state exists) before creating keys programmatically."],"exampleFix":"// before\nconst key = await createApiKey(name);\n// after\nconst machineId = await getMachineId();\nif (!machineId) throw new Error(\"machine not initialized\");\nconst key = await createApiKey(name, machineId);","handlingStrategy":"validation","validationCode":"if (typeof machineId !== \"string\" || machineId.length === 0) {\n  throw new TypeError(\"createApiKey requires a non-empty machineId\");\n}\nawait createApiKey(name, machineId);","typeGuard":"function hasMachineId(x) {\n  return typeof x === \"string\" && x.trim().length > 0;\n}","tryCatchPattern":"try {\n  return await createApiKey(name, machineId);\n} catch (err) {\n  if (err.message === \"machineId is required\") {\n    throw new Error(\"Machine id not initialized — start the app once before creating API keys\");\n  }\n  throw err;\n}","preventionTips":["Always obtain machineId from the app's machine-id helper, never from optional request input alone.","Validate machineId presence in request handlers and return 400 before touching the repo layer.","Initialize the app (first boot) before running key-creation scripts."],"tags":["api-key","validation","missing-argument"],"backgroundTag":"missing-required-parameter","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}