Skip to main content
Version: Next 🚧

Troubleshooting

The golden rule: the Workspace CR tells the story. Phase, conditions and Events carry every admission decision, denial reason and teardown failure β€” start with:

kubectl -n <cr-namespace> describe workspace <name>

Workspace is denied at creation​

Denials read [ReasonCode] human message β€” in the kubectl error, the HTTP 403, the Ready condition and the portal alike.

ReasonMeaningFix
NoPolicyMatchesno WorkspacePolicy matches youship a default policy at priority 0; check your IdP groups are mirrored (they sync at SSO login)
ImageNotInCatalogthe template's image has no WorkspaceImage entryadd/approve the catalog entry with the exact ref
ImageDisabledcatalog kill-switch is offre-enable the wsi
ImageNotAllowedallowedGroups or the policy's image subset excludes youcheck the policy's images and the image's allowedGroups
ProtocolMismatchtemplate declares a protocol the image doesn't servealign protocols with the WorkspaceImage.protocols
ResourcesOutOfBoundssizing outside image min/max or policy capspick a size within bounds
QuotaExceededcount, running count or aggregate over the policy limitdelete/pause something, or raise the policy. "running workspace quota reached" also denies resume β€” expected with maxRunningWorkspaces, pausing another workspace frees the slot (or create the workspace paused)
IdentityViolationspec.owner β‰  your authenticated user, or forged identity annotationsset owner to your own username; never set waas.xorhub.io/* identity annotations
OverrideNotAllowedan override field is not delegated to youtemplate ∩ policy overrides.allowedFields must contain the field
PlacementDeniedthe targetNamespace you asked for is neither the resolved default, nor labeled with your ownership, nor a free name in your waas-<user> territory β€” a name inside your prefix that already belongs to another user is refuseddrop targetNamespace to take the default, or ask an admin (they may place anywhere)

A user whose group mirror is empty matches only subjects-less policies β€” that's the "everyone gets the default policy" symptom, not a priority bug: groups sync from the IdP at every SSO login (or via admin edit).

I was signed out right after changing something about myself​

Expected, and it is the platform telling you so rather than hiding it. Changing your password (Profile page), demoting yourself (Users page) or deactivating / password-resetting your own account through the API revokes every session of that account β€” the one you did it from included. The portal returns you to the login page with a notice naming the reason instead of waiting for the next request to fail.

You cannot be signed back in on the spot: the replacement session would be minted in the same second as the revocation and refused by it. Sign in again with the new password or the new rights.

Two things this is not: editing someone else's account never touches your own session, and an edit that revokes nothing (a quota bump on yourself, for instance) leaves you signed in. If you were signed out without changing anything, read the next section instead.

I cannot demote or deactivate my own admin account​

the platform must keep at least one active administrator β€” promote another
account first

You are the last active administrator. The refusal is deliberate: there is no in-product way back from zero admins, and WAAS_ADMIN_PASSWORD only seeds an empty user table β€” a redeploy would not restore the role, only a manual database edit would. Promote another account to admin, then retry.

A user cannot log in via SSO​

The login page always shows the same generic message β€” "SSO login failed for this account β€” contact an administrator" β€” because the caller is not authenticated yet and a precise message would disclose another account. The reason is in the audit trail, and there are two of them:

Audit actionMeaningFix
user.sso_link_conflictthe IdP's username claim matches an existing account bound to a different subject (or a local one). Treated as an attempted takeover β€” many IdPs let users pick their own username claimrename or delete the conflicting account; never repoint the IdP's sub
user.sso_placement_conflictthe username is distinct, but it normalizes onto an existing account's namespace (alice.smith vs alice_smith)see how names are built β€” usually a stale local account created before SSO was wired; delete it, or rename one side in the directory
# both carry the two usernames and the namespace in their detail
curl -s -H "Authorization: Bearer $TOKEN" \
'https://waas.example.com/api/v1/admin/audit-logs?action=user.sso_placement_conflict' | jq

A user in a non-Latin script (ΠΈΠ²Π°Π½, ηŽ‹δΊ”) is never refused for this reason β€” those resolve through the account id instead.

Workspace Running but not connectable​

  • Ready=True but ConnectionReady=False: the pod runs but the desktop server doesn't listen yet (or crashed). Check the pod logs in the target namespace.
  • The desktop container refuses to start without WAAS_DESKTOP_PASSWORD β€” under the platform this is injected automatically; standalone/custom setups must provide it. Legacy VNC_PW/RDP_PASSWORD are refused with an explicit error.
  • CreateContainerConfigError: a template secretKeyRef resolves in the target namespace, never the platform one β€” and with the per-user default that namespace is not known in advance. Provision the Secret there (External Secrets/Vault), or pin the template to a shared namespace where it is pre-provisioned. See Placement.
  • PullSecretMissing condition: the WorkspaceImage's imagePullSecretRef points at a missing Secret β€” fail-closed, retried automatically once fixed.

The desktop can't reach something on the network​

Placed namespaces carry a default-deny egress policy: DNS is always open, the public internet is allowed minus operator.desktopEgress.blockedCIDRs β€” the cloud IMDS and, by default, every RFC1918 range. So an internal service (package mirror, private Git, on-prem API) is blocked until it is listed in operator.desktopEgress.extraAllowedCIDRs, which wins over the blocked ranges. Symptoms are timeouts, not errors: name resolution keeps working. Full rule set: Placement.

If your CNI does not enforce NetworkPolicy egress, the policy is inert β€” operator.desktopEgress.enabled: false makes that explicit rather than leaving a policy you believe in.

Video works, no sound​

enable-audio alone is not enough over VNC: the template's vnc protocol entry also needs exposeAudioPort: true (opens PulseAudio's 4713 on the container and Service). Without it the session degrades silently. See Templates and protocols.

Workspace stuck in Terminating​

Read the TeardownFailed event/condition on the CR β€” the finalizer retries forever rather than leak silently. Full procedure, including the last-resort finalizer bypass: Workspace deletion.

Paused workspace didn't come back on schedule​

Remember the arbitration rule: a manual action wins until the next scheduled edge of the opposite kind. A manual pause during an uptime window stays down until the next scheduled start β€” that's the contract, not a missed cron. See Workspace lifecycle.

Where the logs are​

ComponentWhat you'll find
operatorreconcile decisions, admission re-checks, teardown/janitor activity
api-serverauth, policy resolution, audit trail, session sweeper
wwtsession/JWT validation, guacd handshakes
desktop podXvnc/xrdp/sshd/supervisord logs, entrypoint warnings (e.g. RDP auth disabled)

All in the platform namespace (kubectl -n waas logs deploy/...), desktop pods in their target namespace.