semaphoreui/semaphore · error
missing secret
Error message
missing secret
What it means
Environment.Validate on an EnvironmentSecret (EnvironmentVar/EnvironmentPassword type) requires the Secret field to be non-empty. Secret-typed environment entries must reference a stored secret value; an empty Secret means the entry carries no credential and would silently resolve to nothing at job runtime, so validation rejects it up front.
Solutions
- Provide a non-empty "secret" value in the environment entry's JSON payload
- If the entry holds a plain value, change its type to EnvironmentSecretVar (or EnvironmentSecretEnv) so the secret check is skipped
- Templating tools: fail fast on empty variables instead of emitting empty strings into the env JSON
Example fix
// before
{"HOME_VAR": {"type": "password", "secret": ""}}
// after
{"HOME_VAR": {"type": "password", "secret": "vault-stored-password"}} Defensive patterns
Strategy: validation
Validate before calling
if entry.Type != "var" && entry.Type != "env" && strings.TrimSpace(entry.Secret) == "" {
return errors.New("secret entry requires a non-empty secret value")
} Type guard
func secretEntryIsValid(s db.EnvironmentSecret) bool {
if s.Type == db.EnvironmentSecretVar || s.Type == db.EnvironmentSecretEnv { return true }
return s.Secret != ""
} Try / catch
if err := env.Validate(); err != nil {
if strings.Contains(err.Error(), "missing secret") {
return fmt.Errorf("environment rejected: %w", err)
}
return err
} Prevention
- Never template secrets with possibly-undefined variables; assert non-empty first
- Use the var/env entry types for plain values, password type only with real secret values
- Run Environment.Validate on composed payloads before calling the API
When it happens
Trigger: Creating or updating an environment via the API (POST/PUT /api/environments) whose JSON env-vars payload contains an entry with type EnvironmentPassword (or a non-var/env type) and an empty/missing "secret" field, validated by Validate.
Common situations: Ansible/Terraform automation templating environment JSON where the secret variable is undefined and renders as an empty string; copying an environment definition between projects and dropping the secret value; users picking the wrong secret type when entering environment variables in the UI.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- secret does not belong to this environment
- invalid environment secret type
- must be valid JSON
- key can not be empty
- values must be scalar
AI-assisted analysis of semaphoreui/semaphore@1774ccb71a (2026-09-07).
Data as JSON: /api/errors/0d9ebfcdaaa5bef8.
Report an issue: GitHub.
Appendix: source
Thrown at db/Environment.go:75
SecretStorageID *int `db:"secret_storage_id" json:"secret_storage_id,omitempty" backup:"-"`
SecretStorageKeyPrefix *string `db:"secret_storage_key_prefix" json:"secret_storage_key_prefix,omitempty"`
// Sync fields are transfer-only; persisted in project__secret_sync.
SyncEnabled bool `db:"-" json:"sync_enabled"`
SyncInterval int `db:"-" json:"sync_interval"`
LastSyncedAt *time.Time `db:"-" json:"last_synced_at,omitempty"`
LastSyncFailedAt *time.Time `db:"-" json:"last_sync_failed_at,omitempty"`
SyncPaths []SecretSyncPath `db:"-" json:"sync_paths"`
}
func (s *EnvironmentSecret) Validate() error {
if s.Type == EnvironmentSecretVar || s.Type == EnvironmentSecretEnv {
return nil
}
if s.Secret == "" {
return errors.New("missing secret")
}
return errors.New("invalid environment secret type")
}
func validateJSON(s string, mustValuesBeScalar bool) error {
if s == "" {
return nil
}
var data map[string]any
err := json.Unmarshal([]byte(s), &data)
if err != nil {
return errors.New("must be valid JSON")
}
for k, v := range data {
if k == "" {View on GitHub (pinned to 1774ccb71a)