ory/hydra · error

When using flag -e, environment variable DSN must be set. Wh

Error message

When using flag -e, environment variable DSN must be set.
When using flag -c, the dsn property should be set.

What it means

After building the persistence driver in the janitor's purge step, RunE checks d.Config().DSN(). If the DSN is still empty (even though flag validation passed), it returns this error explaining that with -e the DSN env var must be set and with -c the dsn config property must be present. Arg validation cannot see the actual env/config values, so this is the runtime fallback check.

Source

Thrown at cmd/cli/handler_janitor.go:128

	if !flagx.MustGetBool(cmd, ReadFromEnv) && len(flagx.MustGetStringSlice(cmd, Config)) == 0 {
		co = append(co, configx.WithValue(config.KeyDSN, args[0]))
	}

	do := append(dOpts,
		driver.DisableValidation(),
		driver.DisablePreloading(),
		driver.WithConfigOptions(co...),
	)

	d, err := driver.New(ctx, do...)
	if err != nil {
		return errors.Wrap(err, "Could not create driver")
	}

	if len(d.Config().DSN()) == 0 {
		//lint:ignore ST1005 formatted error string used in CLI output
		return fmt.Errorf("%s\n%s\n%s\n", cmd.UsageString(),
			"When using flag -e, environment variable DSN must be set.",
			"When using flag -c, the dsn property should be set.")
	}

	p := d.Persister()

	limit := flagx.MustGetInt(cmd, Limit)
	batchSize := flagx.MustGetInt(cmd, BatchSize)

	var routineFlags []string

	if flagx.MustGetBool(cmd, OnlyTokens) {
		routineFlags = append(routineFlags, OnlyTokens)
	}

	if flagx.MustGetBool(cmd, OnlyRequests) {
		routineFlags = append(routineFlags, OnlyRequests)
	}

View on GitHub (pinned to 4174065ffb)

Solutions

  1. Export/set the DSN environment variable before running with -e (e.g. DSN=postgres://... in the CronJob env).
  2. Add the `dsn: ...` property to the config file used with -c.
  3. Verify secret mounting / env_file wiring in the container runtime (kubectl describe pod, docker inspect).
  4. Run `hydra janitor <dsn>` positionally as a simple bypass for one-off runs.

Example fix

// before (k8s CronJob)
env: []
args: ["janitor", "-e", "--tokens"]

// after
env:
  - name: DSN
    valueFrom:
      secretKeyRef: { name: hydra, key: dsn }
args: ["janitor", "-e", "--tokens"]
Defensive patterns

Strategy: validation

Validate before calling

# Verify DSN is actually resolvable before launching with -e:
if [ -z "$DSN" ]; then echo "DSN env var missing for janitor -e" >&2; exit 1; fi
# Or with config: grep -q '^dsn:' hydra.yml || exit 1

Try / catch

// Wrapping RunE-style invocation:
if err := runJanitor(); err != nil {
    if strings.Contains(err.Error(), "DSN must be set") {
        log.Fatal("janitor DSN missing: set DSN env (with -e) or dsn property (with -c)")
    }
    log.Fatal(err)
}

Prevention

When it happens

Trigger: Running `hydra janitor -e` (or with -c) where the DSN environment variable is unset/empty, or the config file lacks the dsn key — driver creation succeeds but config yields an empty DSN.

Common situations: Kubernetes CronJob with -e but the DSN secret not mounted/injected; config file valid YAML but missing the dsn property; DSN defined under the wrong config key or a differently named env var; docker-compose env_file not applied.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03). Data as JSON: /api/errors/0e1fc5227236e369. Report an issue: GitHub.