ory/hydra · error

A DSN is required as a positional argument when not passing

Error message

A DSN is required as a positional argument when not passing any of the following flags:
- Using the environment variable with flag -e, --read-from-env
- Using the config file with flag -c, --config

What it means

The `hydra janitor` CLI Args validation requires a DSN to be resolvable from a positional argument, the environment (-e/--read-from-env), or a config file (-c/--config). If none are present, it prints usage and returns this formatted CLI error instead of starting the janitor.

Source

Thrown at cmd/cli/handler_janitor.go:53

type JanitorHandler struct {
	dOpts []driver.OptionsModifier
}

func newJanitorHandler(dOpts []driver.OptionsModifier) *JanitorHandler {
	return &JanitorHandler{
		dOpts: dOpts,
	}
}

func (*JanitorHandler) Args(cmd *cobra.Command, args []string) error {
	if len(args) == 0 &&
		!flagx.MustGetBool(cmd, ReadFromEnv) &&
		len(flagx.MustGetStringSlice(cmd, Config)) == 0 {

		fmt.Printf("%s\n", cmd.UsageString())
		//lint:ignore ST1005 formatted error string used in CLI output
		return fmt.Errorf("%s\n%s\n%s\n",
			"A DSN is required as a positional argument when not passing any of the following flags:",
			"- Using the environment variable with flag -e, --read-from-env",
			"- Using the config file with flag -c, --config")
	}

	if !flagx.MustGetBool(cmd, OnlyTokens) && !flagx.MustGetBool(cmd, OnlyRequests) && !flagx.MustGetBool(cmd, OnlyGrants) {
		//lint:ignore ST1005 formatted error string used in CLI output
		return fmt.Errorf("%s\n%s\n", cmd.UsageString(),
			"Janitor requires at least one of --tokens, --requests or --grants to be set")
	}

	limit := flagx.MustGetInt(cmd, Limit)
	batchSize := flagx.MustGetInt(cmd, BatchSize)
	if limit <= 0 || batchSize <= 0 {
		//lint:ignore ST1005 formatted error string used in CLI output
		return fmt.Errorf("%s\n%s\n", cmd.UsageString(),
			"Values for --limit and --batch-size should both be greater than 0")
	}

View on GitHub (pinned to 4174065ffb)

Solutions

  1. Pass the DSN positionally: `hydra janitor postgres://user:pass@host/db`.
  2. Or export DSN and run with `hydra janitor -e`.
  3. Or provide a config file: `hydra janitor -c hydra.yml` containing the dsn property.
  4. Fix CI/CD or CronJob manifests so the flag/argument is actually included.

Example fix

// before
command: ["hydra", "janitor", "--requests"]

// after
command: ["hydra", "janitor", "--requests", "-e"]  # with DSN env var set
# or: ["hydra", "janitor", "--requests", "postgres://..."]
Defensive patterns

Strategy: validation

Validate before calling

# Shell guard before invoking janitor:
if [ -z "$DSN" ] && [ $# -lt 1 ]; then
  echo "Provide DSN positionally, or set DSN and pass -e, or pass -c config.yml" >&2
  exit 1
fi

Try / catch

// When embedding janitor Args via SDK:
if err := handler.Args(cmd, args); err != nil {
    fmt.Fprintln(os.Stderr, err)
    os.Exit(1)
}

Prevention

When it happens

Trigger: Running `hydra janitor` (or janitor via SDK's Args) with no positional DSN and without -e or -c flags.

Common situations: Forgetting the DSN argument in a cron job / Kubernetes CronJob command; relying on env vars without passing -e; config file path typo so the flag was never given; upgrading hydra so the old positional argument was dropped from a script.

Related errors


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