Octopus Deploy "(401) Unauthorized" API key error in CI
The octo CLI connected to your Octopus server but the API key it sent was rejected. A 401 means no valid credential was presented: the OCTOPUS_API_KEY secret is empty, malformed, or belongs to a disabled or deleted user.
What this error means
An octo command (create-release, push, deploy-release) fails with "The remote server returned an error: (401) Unauthorized." while the same key works locally, or right after a key was rotated.
Octopus.Client.Exceptions.OctopusSecurityException: The remote server
returned an error: (401) Unauthorized.Common causes
The API key secret is empty or not injected
The step references OCTOPUS_API_KEY but the secret was never set, has a typo in its name, or is not exposed to that job, so octo sends an anonymous request and gets 401.
The key was rotated, disabled, or its user deactivated
An old key value is still stored in CI after rotation, or the service account that owns it was disabled in Octopus, so the credential no longer authenticates.
How to fix it
Inject a valid API key from a CI secret
- Create a fresh API key in Octopus under the service account (Profile, My API Keys).
- Store it as a repository or organization secret named OCTOPUS_API_KEY.
- Pass it to octo with --apiKey and confirm the step reads the secret.
env:
OCTOPUS_API_KEY: ${{ secrets.OCTOPUS_API_KEY }}
OCTOPUS_URL: ${{ secrets.OCTOPUS_URL }}
run: octo create-release --server "$OCTOPUS_URL" --apiKey "$OCTOPUS_API_KEY" --project "Web"Confirm the key belongs to an active user
A rotated or disabled key will not authenticate no matter how many times you retry. Verify the API key still exists in Octopus and that its owning user or service account is enabled.
How to prevent it
- Keep the API key in CI secrets, never committed to the workflow file.
- Use a dedicated service account for CI so key rotation is isolated.
- Update the stored secret in one place immediately after rotating a key.