{"record":{"id":"104be8a78fcf59c4","repo":"remix-run/remix","slug":"throw-new-typeerror-message","errorCode":null,"errorMessage":"throw new TypeError(message)","messagePattern":"throw new TypeError\\(message\\)","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/assets/src/lib/access.ts","lineNumber":162,"sourceCode":"  for (let packageName of packageOption ?? []) {\n    if (typeof packageName !== 'string') {\n      throw new TypeError(`${optionName} values must be strings`)\n    }\n\n    let normalizedPackageName = packageName.trim()\n    if (!isValidPackageName(normalizedPackageName)) {\n      throw new TypeError(`${optionName} values must be package names. Received \"${packageName}\".`)\n    }\n\n    packageNames.add(normalizedPackageName)\n  }\n\n  return packageNames\n}\n\nfunction validatePackageName(packageName: string, message: string): void {\n  if (!isValidPackageName(packageName)) {\n    throw new TypeError(message)\n  }\n}\n\ntype PackageJson = {\n  dependencies?: Record<string, string>\n  optionalDependencies?: Record<string, string>\n}\n\ntype PackageRootPathTrie = {\n  children: Map<string, PackageRootPathTrie>\n  packageName?: string\n}\n\ntype PackageRootQueueItem = {\n  packageJsonPath: string\n  packageName: string\n}\n","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/remix-run/remix/blob/9696913134be3a4423513d2775f7b31d6917c049/packages/assets/src/lib/access.ts#L144-L180","documentation":"`resolveDbString` resolves `RemixDbString` config values of the `{ env, default }` form: it uses `process.env[value.env]` and falls back to `value.default`. An env var that is set but empty is deliberately treated as unset; if the fallback also yields undefined or `''`, there's no usable connection value and it throws. Used for db filenames and connections created from config.","triggerScenarios":"Configuring `db.filename` (or another `RemixDbString`) as `{ env: 'DATABASE_FILE' }` with no `default` while `DATABASE_FILE` is unset or empty — `process.env[value.env] || value.default` resolves to undefined/`''`.","commonSituations":"CI missing the database secret; `.env` not loaded; configs written assuming the env var always exists; pipelines injecting empty-string values.","solutions":["Export the variable with a real value: `export DATABASE_FILE=./data.db`","Add a `\"default\"` fallback in remix.json for local/dev runs","Audit CI secret configuration — the secret may exist but inject an empty value"],"exampleFix":"// before\n{ \"db\": { \"filename\": { \"env\": \"DATABASE_FILE\" } } }\n// after\n{ \"db\": { \"filename\": { \"env\": \"DATABASE_FILE\", \"default\": \"./data.db\" } } }","handlingStrategy":"validation","validationCode":"function resolveDbString(v: { env: string; default?: string }): string {\n  let out = process.env[v.env] || v.default;\n  if (out === undefined || out === '') throw new Error(`${v.env} is not set`);\n  return out;\n}\nlet db = JSON.parse(fs.readFileSync('remix.json','utf8')).db;\nresolveDbString(db.filename); // pre-check before running the CLI","typeGuard":"function hasResolvableConnection(v: any): boolean {\n  if (typeof v === 'string') return v !== '';\n  return Boolean(process.env[v?.env] || v?.default);\n}","tryCatchPattern":null,"preventionTips":["Always include a default for env-based connections","Verify secrets exist in CI before db commands","Empty env values fall back — don't rely on empty-set vars"],"tags":["cli","database","env-var","config"],"backgroundTag":"missing-env-var","analyzedSha":"9696913134be3a4423513d2775f7b31d6917c049","analyzedAt":"2026-08-27T19:55:01.024Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}