{"record":{"id":"d2b634f6394828ce","repo":"Budibase/budibase","slug":"err-message","errorCode":null,"errorMessage":"${err.message}","messagePattern":"\\$\\{err\\.message\\}","errorType":"exception","errorClass":"CouchDBError","httpStatus":null,"severity":"error","filePath":"packages/backend-core/src/db/couch/DatabaseImpl.ts","lineNumber":168,"sourceCode":"\n  private getDb() {\n    return this.nano().db.use(this.name)\n  }\n\n  private async checkAndCreateDb() {\n    let shouldCreate = !this.pouchOpts?.skip_setup\n    // check exists in a lightweight fashion\n    let exists = await this.exists()\n    if (!shouldCreate && !exists) {\n      throw new Error(\"DB does not exist\")\n    }\n    if (!exists) {\n      try {\n        await this.nano().db.create(this.name)\n      } catch (err: any) {\n        // Handling race conditions\n        if (err.statusCode !== 412) {\n          throw new CouchDBError(err.message, err)\n        }\n      }\n    }\n    return this.getDb()\n  }\n\n  // this function fetches the DB and handles if DB creation is needed\n  private async performCallWithDBCreation<T>(\n    call: DBCallback<T>\n  ): Promise<any> {\n    const db = this.getDb()\n    const fnc = await call(db)\n    try {\n      return await fnc()\n    } catch (err: any) {\n      if (err.statusCode === 404 && err.reason === DATABASE_NOT_FOUND) {\n        await this.checkAndCreateDb()\n        return await this.performCallWithDBCreation(call)","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/backend-core/src/db/couch/DatabaseImpl.ts#L150-L186","documentation":"When the DB does not exist and auto-create is enabled, checkAndCreateDb calls nano.db.create. Any creation failure other than the benign 412 'already exists' race is rethrown as a CouchDBError carrying the original message. It surfaces underlying CouchDB failures (auth, connectivity, naming) during DB provisioning.","triggerScenarios":"Auto-creating a DB while CouchDB returns an error: admin party disabled and missing credentials (401), connection refused, invalid DB name (400, illegal characters/case), or out-of-disk/quota server errors — anything with statusCode !== 412.","commonSituations":"Wrong COUCH_DB_URL/user/password env vars, DB names containing uppercase or invalid chars, CouchDB restarted or unreachable, race where two nodes create and one hits a non-412 error (e.g. 401/500).","solutions":["Verify CouchDB credentials and URL env vars (COUCH_DB_URL, user, password)","Validate the DB name (must be lowercase, /^[a-z][a-z0-9_$()+-]*$/)","Check CouchDB availability/health and disk space; fix server-side issue then retry","Inspect the wrapped err passed to CouchDBError for the root statusCode/reason"],"exampleFix":"// before\ntry { await db.put(doc) } catch (e) { /* opaque CouchDBError */ }\n// after\ntry { await db.put(doc) } catch (e) {\n  if (e.statusCode === 412) { /* already exists - ignore */ }\n  else throw e\n}","handlingStrategy":"retry","validationCode":"const validName = /^[a-z][a-z0-9_$()+-]*$/.test(dbName)\nif (!validName) throw new Error(`Invalid CouchDB name: ${dbName}`)","typeGuard":null,"tryCatchPattern":"try {\n  await db.put(doc)\n} catch (err) {\n  if (err instanceof CouchDBError && err.statusCode === 412) {\n    // DB already exists - safe to continue\n  } else throw err\n}","preventionTips":["Keep COUCH_DB_URL/credentials verified in health checks","Sanitize DB names to CouchDB rules (lowercase, allowed chars)","Retry with backoff on transient creation failures; treat 412 as success"],"tags":["couchdb","network","authentication","database-creation"],"backgroundTag":"couchdb-database-creation-failed","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}