gastownhall/beads · error

--auth-token-file

Error message

--auth-token-file: %w

What it means

resolveServeConfig wraps failures from NewTokenFileAuth (reading/validating the --auth-token-file) with an --auth-token-file prefix so the CLI flag is named in the error. Thrown when the token file is missing, unreadable, or contains invalid token content.

Solutions

  1. Verify the token file exists and is readable by the serve process user.
  2. Check the file contains valid token content (non-empty, correct format per NewTokenFileAuth).
  3. Fix permissions (chmod/chown) or point the flag at the correct secret path.
  4. Use errors.As to inspect the wrapped cause from NewTokenFileAuth for the precise read/parse error.

Example fix

// before
tokPath := flagValue
// after
if info, err := os.Stat(tokPath); err != nil || info.IsDir() {
    return fmt.Errorf("--auth-token-file %s not readable", tokPath)
}
Defensive patterns

Strategy: validation

Validate before calling

if info, err := os.Stat(tokenFile); err != nil || info.IsDir() {
    return fmt.Errorf("--auth-token-file %s missing or invalid", tokenFile)
}

Try / catch

cfg, err := resolveServeConfig(...)
if err != nil {
    var msg string
    if strings.Contains(err.Error(), "--auth-token-file:") { /* inspect flag value and file */ }
    _ = msg
    return err
}

Prevention

When it happens

Trigger: Running `bd serve --auth-token-file <path>` where the file does not exist, lacks read permission, is empty/invalid, or when httpapi.ValidateAuthPosture accepts the combination but the token file cannot be materialized into an auth provider.

Common situations: Stale path to a token file after restart; systemd/daemon unit pointing at a secret that was rotated or deleted; token file mounted with wrong permissions in containers; typo in the flag value.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/5f70bc1195b45b29. Report an issue: GitHub.

Appendix: source

Thrown at cmd/bd/serve.go:237

		AllowNonLoopback: serveAllowNonLoopback,
		InsecureNoAuth:   serveInsecureNoAuth,
		AllowedHosts:     serveAllowedHosts,
	}
	if _, err := httpapi.ValidateBindAddr(serveAddr, serveAllowNonLoopback); err != nil {
		return cfg, err
	}

	tokenFile := serveAuthTokenFile
	if tokenFile == "" {
		tokenFile = os.Getenv(serveTokenFileEnv)
	}
	if err := httpapi.ValidateAuthPosture(serveAllowNonLoopback, tokenFile != "", serveInsecureNoAuth); err != nil {
		return cfg, err
	}
	if tokenFile != "" {
		auth, err := httpapi.NewTokenFileAuth(tokenFile)
		if err != nil {
			return cfg, fmt.Errorf("--auth-token-file: %w", err)
		}
		cfg.Auth = auth
	}

	for _, host := range serveAllowedHosts {
		if err := httpapi.ValidateAllowedHost(host); err != nil {
			return cfg, err
		}
	}
	return cfg, nil
}

func runServe() error {
	// Flag validation first: it depends on nothing about the workspace, so the
	// refusal for a bad --addr or an unservable auth posture is the same in
	// every mode, and it lands before anything opens a database.
	opts, err := resolveServeConfig()
	if err != nil {

View on GitHub (pinned to 71377f2769)