louislam/uptime-kuma · error · Error

Both ${envName} and ${envName}_FILE are set. Please use only

Error message

Both ${envName} and ${envName}_FILE are set. Please use only one.

What it means

Thrown by getEnvOrFile(envName) in setup-database.js when BOTH the direct environment variable (e.g. UPTIME_KUMA_DB_PASSWORD) and its Docker-secrets variant with the _FILE suffix are set simultaneously. The helper disallows ambiguity: only one source of a config value is permitted.

Source

Thrown at server/setup-database.js:24

const Database = require("./database");
const { allowDevAllOrigin, printServerUrls } = require("./util-server");
const mysql = require("mysql2/promise");
const { isSSL, sslKey, sslCert, sslKeyPassphrase } = require("./config");
const https = require("https");

/**
 * Reads a configuration value from an environment variable or a Docker secrets file.
 * If both the direct env var and the _FILE variant are set, an error is thrown.
 * @param {string} envName The base name of the environment variable (e.g., "UPTIME_KUMA_DB_PASSWORD")
 * @returns {string|undefined} The value from the env var, file contents (trimmed), or undefined if neither is set
 * @throws {Error} If both the direct env var and the _FILE variant are set
 */
function getEnvOrFile(envName) {
    const directValue = process.env[envName];
    const fileValue = process.env[envName + "_FILE"];

    if (directValue && fileValue) {
        throw new Error(`Both ${envName} and ${envName}_FILE are set. Please use only one.`);
    }

    if (fileValue) {
        try {
            return fs.readFileSync(fileValue, "utf8").trim();
        } catch (err) {
            throw new Error(`Failed to read ${envName}_FILE at ${fileValue}: ${err.message}`);
        }
    }

    return directValue;
}

/**
 *  A standalone express app that is used to setup a database
 *  It is used when db-config.json and kuma.db are not found or invalid
 *  Once it is configured, it will shut down and start the main server
 */

View on GitHub (pinned to 6b5ea01557)

Solutions

  1. Remove one of the two variables from the environment (docker-compose env/compose env_file, Kubernetes secret/envFrom, or shell export).
  2. Keep UPTIME_KUMA_DB_PASSWORD_FILE pointing at /run/secrets/<name> and unset the plain UPTIME_KUMA_DB_PASSWORD.
  3. Restart the container/process so the helper sees only the single source.

Example fix

# before
environment:
  - UPTIME_KUMA_DB_PASSWORD=kuma
  - UPTIME_KUMA_DB_PASSWORD_FILE=/run/secrets/db_password
# after
environment:
  - UPTIME_KUMA_DB_PASSWORD_FILE=/run/secrets/db_password
Defensive patterns

Strategy: validation

Validate before calling

// Startup guard before booting the app
function assertNoDuplicateEnv(envName) {
  if (process.env[envName] && process.env[envName + "_FILE"]) {
    throw new Error(`Unset one of ${envName} / ${envName}_FILE before starting.`);
  }
}
["UPTIME_KUMA_DB_PASSWORD", "UPTIME_KUMA_DB_USERNAME"].forEach(assertNoDuplicateEnv);

Type guard

function isSingleEnvSource(envName) {
  const d = process.env[envName], f = process.env[envName + "_FILE"];
  return !(d && f);
}

Try / catch

try {
  require("./setup-database");
} catch (e) {
  if (/Both .* and .*_FILE are set/.test(e.message)) {
    failDeployment("Remove one of the duplicate env vars in compose/manifest.");
  } else throw e;
}

Prevention

When it happens

Trigger: Container/host environment exports both UPTIME_KUMA_DB_PASSWORD and UPTIME_KUMA_DB_PASSWORD_FILE (or any envName handled via getEnvOrFile). Detected at startup before the database setup express app can proceed, blocking boot.

Common situations: Docker compose file sets the password directly and also mounts a Docker secret with the same suffix; CI secret manager injects both forms; legacy .env left in place after migrating to _FILE secrets.

Related errors


AI-assisted analysis of louislam/uptime-kuma@6b5ea01557 (2026-08-12). Data as JSON: /api/errors/6ec3558e7ffe4291. Report an issue: GitHub.