semaphoreui/semaphore · error

invalid access token type

Error message

invalid access token type

What it means

SerializeSecret switches on the access key's Type to decide what plaintext to encrypt. Recognized types are SSH, LoginPassword, and None (which stores no secret); any other Type value hits the default branch and returns 'invalid access token type'. The key carries a type enum value the serializer does not know.

Solutions

  1. Set the access key's Type to a supported value: ssh, login_password, or none.
  2. Upgrade Semaphore to a version that supports the key type present in the data.
  3. Delete and recreate the affected access keys with a valid type via the API/UI.

Example fix

// before
type: 7 // unknown
type: "login_password"
Defensive patterns

Strategy: validation

Validate before calling

switch key.Type {
case db.AccessKeySSH, db.AccessKeyLoginPassword, db.AccessKeyNone:
    // ok
default:
    // unsupported type: fix before SerializeSecret
}

Try / catch

if err := svc.SerializeSecret(key); err != nil && err.Error() == "invalid access token type" { /* recreate key with a supported type */ }

Prevention

When it happens

Trigger: SerializeSecret (e.g. from RekeyAccessKeys) on an AccessKey whose db.AccessKey Type is an unrecognized value (corrupted enum, future/new type unknown to this binary, or 0/garbage value).

Common situations: Rows migrated from another install with unmapped type values; manual DB edits; running an older Semaphore binary against data written by a newer version with a new access key type.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at services/server/access_key_serializer_local.go:68

		}
	case db.AccessKeyLoginPassword:
		if key.LoginPassword.Password == "" {
			if key.LoginPassword.Login != "" {
				return fmt.Errorf("invalid password key")
			}
			key.Secret = nil
			return nil
		}

		plaintext, err = json.Marshal(key.LoginPassword)
		if err != nil {
			return err
		}
	case db.AccessKeyNone:
		key.Secret = nil
		return nil
	default:
		return fmt.Errorf("invalid access token type")
	}

	secret, err := util.Config.EncryptAccessSecret(plaintext)
	if err != nil {
		return err
	}
	key.Secret = &secret

	return nil
}

func (d *LocalAccessKeyDeserializer) DeserializeSecret(key *db.AccessKey) (res string, err error) {
	return d.deserialize(key, func(stored string) ([]byte, error) {
		return util.Config.DecryptAccessSecret(stored)
	})
}

// DeserializeSecret2 decrypts using a single explicit key (stripping any key-id

View on GitHub (pinned to 1774ccb71a)