semaphoreui/semaphore · error

invalid key format

Error message

invalid key format

What it means

ValidateOptionKey checks that an option key matches the regex ^[\w.]+$ (only word characters and dots). Keys with spaces, slashes, dashes, or empty strings are rejected with 'invalid key format'. It is invoked by GetOptions, DeleteOption, and DeleteOptions before touching the options store.

Solutions

  1. Sanitize the key to only [A-Za-z0-9_.] characters before calling the option APIs
  2. Replace disallowed characters such as '/' and '-' with '.' or '_' when composing keys
  3. Call ValidateOptionKey yourself (or apply the same regex) on user input before persisting it as a key

Example fix

// before
opts, err := db.GetOptions(tx, []string{"apps/" + appID})
// after
key := strings.ReplaceAll("apps."+appID, "/", "_")
opts, err := db.GetOptions(tx, []string{key})
Defensive patterns

Strategy: validation

Validate before calling

var keyRe = regexp.MustCompile(`^[\w.]+$`)
func validOptionKey(k string) bool { return keyRe.MatchString(k) }

Try / catch

if err := db.ValidateOptionKey(key); err != nil {
    return fmt.Errorf("option key %q rejected: %w", key, err)
}
// then proceed with GetOptions/DeleteOption

Prevention

When it happens

Trigger: Calling db.GetOptions, DeleteOption, or DeleteOptions with keys like 'apps/myapp', 'my-app', '' (empty), or containing spaces/special characters.

Common situations: Building option keys by concatenating IDs that contain slashes or hyphens (e.g. 'apps.' + a UUID with dashes is fine, but a path-like id is not); user-supplied keys passed through unvalidated; empty key after string formatting.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of semaphoreui/semaphore@1774ccb71a (2026-09-07). Data as JSON: /api/errors/c578fd98b1c0900e. Report an issue: GitHub.

Appendix: source

Thrown at db/Option.go:20

import (
	"fmt"
	"regexp"
)

type Option struct {
	Key   string `db:"key" json:"key"`
	Value string `db:"value" json:"value"`
}

func ValidateOptionKey(key string) error {
	m, err := regexp.Match(`^[\w.]+$`, []byte(key))
	if err != nil {
		return err
	}

	if !m {
		return fmt.Errorf("invalid key format")
	}

	return nil
}

View on GitHub (pinned to 1774ccb71a)