ory/kratos · error

required config value "dsn" was not set

Error message

required config value "dsn" was not set

What it means

After initializing the driver with the collected config options, CleanupSQL checks `d.Config().DSN(ctx)`. If the resolved DSN is empty — meaning no DSN was provided via argument, env (read-from-env), or config file — the command aborts. This error fires when the DSN path was taken (flag or arg present) but the value still resolved to empty, or driver init produced no DSN.

Solutions

  1. Verify the DSN environment variable is actually set and non-empty in the runtime environment
  2. Pass the DSN explicitly as an argument instead of relying on env
  3. Check the config file loaded by configx contains a non-empty dsn key
  4. Inspect logs or echo the env in the job to confirm variable propagation

Example fix

// before (env var missing)
DSN= cleanup sql --read-from-env
// after
export DSN='postgres://user:pass@host:5432/db?sslmode=disable'
cleanup sql --read-from-env
Defensive patterns

Strategy: validation

Validate before calling

if os.Getenv("DSN") == "" && dsnArg == "" {
  return errors.New("DSN must be set via argument or env before running cleanup")
}

Prevention

When it happens

Trigger: Calling `cleanup sql --read-from-env` when the DSN env var is unset/empty; passing an empty-string argument `cleanup sql ""`; a config file that lacks the dsn key while validation was skipped (SkipValidation is used in the opts).

Common situations: Container/CI environments where the DSN env var was not propagated to the cleanup job; typos in the env var name; empty secret mounted for the DSN.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of ory/kratos@b86338da04 (2026-09-07). Data as JSON: /api/errors/05ba21fed1d890ab. Report an issue: GitHub.

Appendix: source

Thrown at cmd/cleanup/handler.go:45

	opts := []configx.OptionModifier{
		configx.WithFlags(cmd.Flags()),
		configx.SkipValidation(),
	}

	if !flagx.MustGetBool(cmd, "read-from-env") {
		if len(args) != 1 {
			return errors.New(`expected to get the DSN as an argument, or the "read-from-env" flag`)
		}
		opts = append(opts, configx.WithValue(config.ViperKeyDSN, args[0]))
	}

	d, err := driver.NewWithoutInit(
		cmd.Context(),
		cmd.ErrOrStderr(),
		driver.WithConfigOptions(opts...),
	)
	if len(d.Config().DSN(cmd.Context())) == 0 {
		return errors.New(`required config value "dsn" was not set`)
	} else if err != nil {
		return errors.Wrap(err, "An error occurred initializing cleanup")
	}

	err = d.Init(cmd.Context(), &contextx.Default{})
	if err != nil {
		return errors.Wrap(err, "An error occurred initializing cleanup")
	}

	keepLast := flagx.MustGetDuration(cmd, "keep-last")

	err = d.Persister().CleanupDatabase(
		cmd.Context(),
		d.Config().DatabaseCleanupSleepTables(cmd.Context()),
		keepLast,
		d.Config().DatabaseCleanupBatchSize(cmd.Context()))
	if err != nil {
		return errors.Wrap(err, "An error occurred while cleaning up expired data")

View on GitHub (pinned to b86338da04)