{"record":{"id":"a1da40e9b1882f1c","repo":"louislam/uptime-kuma","slug":"invalid-db-config-json-type-must-be-a-string","errorCode":null,"errorMessage":"Invalid db-config.json, type must be a string","messagePattern":"Invalid db-config\\.json, type must be a string","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"server/database.js","lineNumber":216,"sourceCode":"\n    /**\n     * Read the database config\n     * @throws {Error} If the config is invalid\n     * @typedef {string|undefined} envString\n     * @returns {{type: \"sqlite\"} | {type:envString, hostname:envString, port:envString, database:envString, username:envString, password:envString, socketPath:envString}} Database config\n     */\n    static readDBConfig() {\n        let dbConfig;\n\n        let dbConfigString = fs.readFileSync(path.join(Database.dataDir, \"db-config.json\")).toString(\"utf-8\");\n        dbConfig = JSON.parse(dbConfigString);\n\n        if (typeof dbConfig !== \"object\") {\n            throw new Error(\"Invalid db-config.json, it must be an object\");\n        }\n\n        if (typeof dbConfig.type !== \"string\") {\n            throw new Error(\"Invalid db-config.json, type must be a string\");\n        }\n        return dbConfig;\n    }\n\n    /**\n     * @typedef {string|undefined} envString\n     * @param {{type: \"sqlite\"} | {type:envString, hostname:envString, port:envString, database:envString, username:envString, password:envString, socketPath:envString}} dbConfig the database configuration that should be written\n     * @returns {void}\n     */\n    static writeDBConfig(dbConfig) {\n        fs.writeFileSync(path.join(Database.dataDir, \"db-config.json\"), JSON.stringify(dbConfig, null, 4));\n    }\n\n    /**\n     * Connect to the database\n     * @param {boolean} testMode Should the connection be started in test mode?\n     * @param {boolean} autoloadModels Should models be automatically loaded?\n     * @param {boolean} noLog Should logs not be output?","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/louislam/uptime-kuma/blob/6b5ea0155793e666666745fb8d6fef1e829543a2/server/database.js#L198-L234","documentation":"Second guard in readDBConfig(): after confirming dbConfig is an object, it requires dbConfig.type to be a string. Throws when the type field is missing, null, a number, or any non-string value. null and undefined both fail typeof === 'string', so a `{}` or `{ \"type\": null }` file lands here. This is the most common form of db-config corruption because type is the one mandatory field.","triggerScenarios":"db-config.json exists and is an object but lacks the `type` key (e.g. `{}`); type is set to a non-string; the file was generated by a tool that serialised only connection params and forgot the type discriminator.","commonSituations":"Custom provisioning scripts that build the config programmatically; manual editing that accidentally deleted the type line; a partial migration that wrote hostname/port but dropped type.","solutions":["Ensure db-config.json has `\"type\": \"sqlite\"` (or \"mariadb\" / \"embedded-mariadb\") as a string at the top level.","For MariaDB the minimal shape is `{ \"type\": \"mariadb\", \"hostname\": \"...\", \"port\": 3306, \"database\": \"...\", \"username\": \"...\", \"password\": \"...\" }`.","Recreate the file via the setup wizard if you are unsure of the exact schema.","Lint the file: `node -e \"const c=require('./data/db-config.json'); console.log(typeof c.type)\"` must print 'string'."],"exampleFix":"// before — data/db-config.json\n{}\n\n// after\n{\n    \"type\": \"sqlite\"\n}","handlingStrategy":"type-guard","validationCode":"const fs = require(\"fs\"); const path = require(\"path\");\nfunction ensureTypeString(dataDir) {\n    const cfg = JSON.parse(fs.readFileSync(path.join(dataDir, \"db-config.json\"), \"utf-8\"));\n    if (typeof cfg?.type !== \"string\") {\n        throw new Error(`db-config.json: expected 'type' to be a string, got ${typeof cfg?.type}`);\n    }\n    return cfg;\n}","typeGuard":"function hasStringType(v) {\n    return v !== null && typeof v === \"object\" && typeof v.type === \"string\";\n}","tryCatchPattern":"try {\n    dbConfig = Database.readDBConfig();\n} catch (e) {\n    if (/type must be a string/.test(e.message)) {\n        // rewrite db-config.json with the correct type field, then retry\n    }\n    throw e;\n}","preventionTips":["Always include `\"type\": \"sqlite\"|\"mariadb\"|\"embedded-mariadb\"` in db-config.json.","Use the setup wizard to write the file rather than editing by hand.","After provisioning, assert the type field with a smoke-test script."],"tags":["database","config","startup"],"backgroundTag":null,"analyzedSha":"6b5ea0155793e666666745fb8d6fef1e829543a2","analyzedAt":"2026-08-12T23:42:12.959Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}