{"record":{"id":"ba501557e153aec1","repo":"Budibase/budibase","slug":"unable-to-get-bulk-documents-missingids","errorCode":null,"errorMessage":"Unable to get bulk documents: ${missingIds}","messagePattern":"Unable to get bulk documents: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/backend-core/src/db/couch/DatabaseImpl.ts","lineNumber":262,"sourceCode":"    })\n    const rowUnavailable = (row: RowResponse<T>) => {\n      // row is deleted - key lookup can return this\n      if (\n        (includeDocs && row.doc == null) ||\n        (row.value && \"deleted\" in row.value && row.value.deleted)\n      ) {\n        return true\n      }\n      return row.error === \"not_found\"\n    }\n\n    const rows = response.rows.filter(row => !rowUnavailable(row))\n    const someMissing = rows.length !== response.rows.length\n    // some were filtered out - means some missing\n    if (!opts?.allowMissing && someMissing) {\n      const missing = response.rows.filter(row => rowUnavailable(row))\n      const missingIds = missing.map(row => row.key).join(\", \")\n      throw new Error(`Unable to get bulk documents: ${missingIds}`)\n    }\n    return rows.map(row => (includeDocs ? row.doc! : row.value))\n  }\n\n  async remove(idOrDoc: string | Document, rev?: string) {\n    // not a read call - but don't create a DB to delete a document\n    return this.performCall(db => {\n      let _id: string\n      let _rev: string\n\n      if (isDocument(idOrDoc)) {\n        _id = idOrDoc._id!\n        _rev = idOrDoc._rev!\n      } else {\n        _id = idOrDoc\n        _rev = rev!\n      }\n","sourceCodeStart":244,"sourceCodeEnd":280,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/backend-core/src/db/couch/DatabaseImpl.ts#L244-L280","documentation":"getMultiple fetches many docs by id via bulk fetch; CouchDB returns a row for every requested key with an 'error' entry for missing ones. Unless allowMissing is set, any missing row causes an error listing the missing ids, since partial results would be silently wrong.","triggerScenarios":"Calling getMultiple(ids) where one or more ids do not exist in the DB and opts.allowMissing is not true.","commonSituations":"Stale id lists after deletions, ids from another tenant/environment's DB, race between listing and fetching, users deleting docs while a batch job runs.","solutions":["Pass { allowMissing: true } if partial results are acceptable and handle absent docs downstream","Filter the id list against existing docs before bulk fetching, or re-fetch after deletion races","Treat the error message's missingIds list to reconcile/clean the source data"],"exampleFix":"// before\nconst docs = await db.getMultiple(ids) // throws on any missing\n// after\nconst rows = await db.getMultiple(ids, { allowMissing: true })\nconst found = rows.filter(Boolean)","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const docs = await db.getMultiple(ids)\n} catch (err) {\n  if (err.message.startsWith(\"Unable to get bulk documents\")) {\n    // retry with allowMissing or resync the id list\n    const partial = await db.getMultiple(ids, { allowMissing: true })\n  } else throw err\n}","preventionTips":["Use { allowMissing: true } when partial reads are acceptable","Re-list ids close in time to the bulk fetch to reduce deletion races","Confirm ids come from the same tenant/DB"],"tags":["couchdb","batch","missing-document"],"backgroundTag":"bulk-fetch-missing-documents","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}