Skip to content

Latest commit

 

History

History
264 lines (181 loc) · 7.95 KB

troubleshooting.md

File metadata and controls

264 lines (181 loc) · 7.95 KB

Troubleshooting

Quick diagnostics

Run these first:

teams auth doctor --output json
teams auth status --output json
teams config show --output json

Add verbose stderr logs:

RUST_LOG=teams=debug teams chat list --output json

AUTH_TOKEN_EXPIRED

Meaning: the keyring access token is expired and could not be refreshed automatically.

The CLI now silently redeems the stored refresh token when the access token is expired or about to expire, so this error normally only appears when no refresh token is stored or the refresh request is rejected (for example the refresh token expired or was revoked).

Resolution:

teams auth login --device-code

AUTH_FAILED or login fails

Check:

  • Tenant allows user consent or admin consent has been granted.
  • The OSO app is allowed by enterprise app policy.
  • BYO profile has auth_app = "byo" and a valid client_id.
  • Browser PKCE redirect http://localhost:8400/callback is allowed.
  • Device-code login is used for SSH or remote terminals.

Useful command:

teams auth consent-url --tenant-id <tenant-id-or-domain> --output json

PERMISSION_DENIED

Common causes:

  • Admin consent has not been granted.
  • The signed-in user is not a member of the team, channel, chat, or meeting roster.
  • The Graph API does not support the operation with the token type used.
  • A Teams policy blocks the action.
  • Client credentials were used for a delegated-only operation.

A PERMISSION_DENIED now carries a Hint: naming the permissions the token actually holds — its delegated scopes, or its application roles when the token is app-only. Graph often answers 403 with an empty message, so this is frequently the only thing to go on: compare the list against the permission the operation needs. An opaque (non-JWT) token yields no claims and gets no hint.

Check token type:

teams auth doctor --output json | jq '.data.token.auth_type'

For normal message sends, this must be delegated.

App-only token rejected for message commands

Message mutation commands require delegated auth for normal live Teams usage:

teams auth login --device-code

Do not use:

teams auth login --client-credentials

for normal chat/channel message posting.

chat list works but message list --chat gets 403

This can happen with meeting chats. The chat can appear in the list, but message reads fail if the signed-in user is not in the roster for that thread.

Agent behavior:

  • Log the chat ID and Graph request ID.
  • Skip that chat.
  • Continue processing other chats.

Do not treat one inaccessible chat as a global auth failure.

team list returns an empty array

team list uses /me/joinedTeams. It returns teams where the user is a direct member. It does not mean the user has no chats, meetings, or shared-channel context.

Try:

teams chat list --output json
teams search teams --query "<name>" --output json

team list and $top

Microsoft Graph currently says /me/joinedTeams does not support OData query parameters to customize the response. The CLI avoids $top for this endpoint.

macOS keychain prompts

Symptoms:

  • macOS asks for the login keychain password when running teams, sometimes on every invocation.
  • Clicking "Always Allow" does not stop the prompts.
  • Prompts return after upgrading the CLI or building it from source.

Cause: macOS binds keychain access grants to the exact code signature of the binary. The released binaries are ad-hoc signed, so every upgrade produces what macOS considers a different application, and a grant made for one build does not carry over to the next. Local builds from source each count as another distinct application for the same reason. The stored items are visible with:

security find-generic-password -s teams-cli

Debug builds from source keep their tokens under the separate service teams-cli-dev (see "Storage namespace" in CONTRIBUTING.md), so rebuilding from source does not, by default, touch the installed release's items. teams --version names the namespace of any build that does not use teams-cli.

Actions:

  • Expect one prompt per profile after upgrading or rebuilding; approve it and the grant holds until the binary changes again.
  • A denied prompt or a locked keychain (common over SSH) fails with KEYRING_ERROR (exit code 10), not "Not authenticated". Unlock the keychain (security unlock-keychain) or use TEAMS_CLI_TOKEN_STORE=file.
  • An unattended process (a daemon, a scheduled job) cannot answer the prompt and waits on it. Set TEAMS_CLI_TOKEN_STORE=file for that process and sign in once with it set; tokens then live in 0600 files under the config directory and no keychain dialog is involved.
  • Re-signing with a self-signed certificate did not stop the prompts when tested on macOS 26 with this CLI's keychain library: each rebuild signed with the same trusted certificate and identifier was asked again, even after "Always Allow" on the previous one. The signature carries no Apple-issued team identifier, and the keychain appears to tie the item to the build instead.
  • In tests only, set TEAMS_CLI_DISABLE_KEYRING=1 so the suite never touches the real keychain.

Do not set TEAMS_CLI_DISABLE_KEYRING=1 for real usage; it prevents token storage.

Windows keyring issues

Symptoms:

  • Auth commands hang.
  • Credential Manager prompts appear.
  • CI tests block when touching real credentials.

Actions:

  • Use a normal user session, not a locked-down service desktop, for interactive login.
  • Run PowerShell as the same user that will run teams.
  • Check Windows Credential Manager for teams-cli entries. A signed-in profile has a <profile>:token header entry plus <profile>:token:0, <profile>:token:1, ... entries holding the token itself, because Credential Manager caps a single credential at 2560 bytes. Versions up to 0.4.0 wrote one entry and failed with KEYRING_ERROR ... longer than platform limit of 2560 chars whenever the token bundle was larger than that.
  • In tests only, set TEAMS_CLI_DISABLE_KEYRING=1.

PowerShell:

$env:TEAMS_CLI_DISABLE_KEYRING = "1"
cargo test --all-targets --all-features

Do not set TEAMS_CLI_DISABLE_KEYRING=1 for real usage; it prevents token storage.

Linux keyring issues

The keyring crate usually needs a Secret Service-compatible backend.

In headless Linux CI, prefer one of:

  • Use TEAMS_CLI_ACCESS_TOKEN for short-lived tests.
  • Run CLI tests with TEAMS_CLI_DISABLE_KEYRING=1.
  • Install and configure a keyring backend if testing real login.
  • On a server or in a container with no Secret Service, set TEAMS_CLI_TOKEN_STORE=file to keep tokens in 0600 files under the config directory instead.

Browser login callback fails

Browser login uses PKCE and the redirect URI:

http://localhost:8400/callback

Check:

  • Port 8400 is free.
  • Local firewall allows loopback.
  • BYO app registration includes that redirect URI.
  • Use --device-code if a browser callback is not possible.

Rate limiting

Exit code 6 means rate limited after retries.

The shared Graph client honors Retry-After when Microsoft Graph sends it. For agents, add higher-level backoff and avoid parallel fan-out into large tenants.

Invalid config

Show the current file path:

teams config path

Inspect config:

teams config show --output json

Recreate a minimal config:

mv "$(teams config path --output plain | awk '/path:/ {print $2}')" config.toml.bak
teams config init

Raw file bytes in terminal

teams file download writes raw bytes to stdout when --path is omitted. Use:

teams file download --team "$TEAM_ID" --channel "$CHANNEL_ID" --file-id "$FILE_ID" --path ./download.bin

Webhook subscription validation

Microsoft Graph requires a public HTTPS notification URL. teams listen is local HTTP.

For local testing:

teams listen --port 8080

Expose it with a trusted HTTPS tunnel, then create the subscription with the tunnel URL.