semaphoreui/semaphore · error
invalid ssh key
Error message
invalid ssh key
What it means
SerializeSecret for a local-stored SSH-type access key requires consistency: if there is no private key, the key may not carry a login or passphrase either — such a key is meaningless. Instead of silently saving a hollow SSH key, SerializeSecret returns 'invalid ssh key' so RekeyAccessKeys fails loudly.
Solutions
- Provide the SshKey.PrivateKey value for the access key before serializing.
- Clear SshKey.Login and SshKey.Passphrase if the key is intentionally key-less, or change the key type to LoginPassword/None.
- Fix the client code that constructs the AccessKey so a complete SshKey is always submitted.
Example fix
// before
key.SshKey = db.SshKey{Login: "deploy"}
// after
key.SshKey = db.SshKey{PrivateKey: privPEM, Login: "deploy", Passphrase: "..."} Defensive patterns
Strategy: validation
Validate before calling
if key.Type == db.AccessKeySSH && key.SshKey.PrivateKey == "" && (key.SshKey.Login != "" || key.SshKey.Passphrase != "") {
// invalid: supply PrivateKey or clear Login/Passphrase
} Try / catch
if err := svc.SerializeSecret(key); err != nil && err.Error() == "invalid ssh key" { /* fix key fields before retry */ } Prevention
- Require the private key field in SSH key creation forms and API clients.
- Never persist partial SSH keys; validate before saving.
- Run RekeyAccessKeys only after a data-integrity pass on SSH keys.
When it happens
Trigger: Calling SerializeSecret (typically during RekeyAccessKeys re-encryption) on an AccessKey of type AccessKeySSH whose SshKey.PrivateKey is empty while SshKey.Login or SshKey.Passphrase is non-empty.
Common situations: Partial key creation where the private key upload failed but login/passphrase fields were saved; API clients sending SSH keys with only login/passphrase; data corrupted by partial updates.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- missing secret
- secret must be valid json in key
- invalid password key
- invalid access key type
- unsupported source storage type
AI-assisted analysis of semaphoreui/semaphore@1774ccb71a (2026-09-07).
Data as JSON: /api/errors/1eccb03d6c00994a.
Report an issue: GitHub.
Appendix: source
Thrown at services/server/access_key_serializer_local.go:41
// No-op for local deserializer
return nil
}
func (d *LocalAccessKeyDeserializer) SerializeSecret(key *db.AccessKey) error {
var plaintext []byte
var err error
switch key.Type {
case db.AccessKeyString:
if key.String == "" {
key.Secret = nil
return nil
}
plaintext = []byte(key.String)
case db.AccessKeySSH:
if key.SshKey.PrivateKey == "" {
if key.SshKey.Login != "" || key.SshKey.Passphrase != "" {
return fmt.Errorf("invalid ssh key")
}
key.Secret = nil
return nil
}
plaintext, err = json.Marshal(key.SshKey)
if err != nil {
return err
}
case db.AccessKeyLoginPassword:
if key.LoginPassword.Password == "" {
if key.LoginPassword.Login != "" {
return fmt.Errorf("invalid password key")
}
key.Secret = nil
return nil
}
View on GitHub (pinned to 1774ccb71a)