> ## Documentation Index
> Fetch the complete documentation index at: https://docs.joystream.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Credential problems

> Missing credentials, GitHub scopes, resolution surprises, and what each error contract means.

## GitHub credential required

```text theme={null}
GitHub credential required.

Connect a GitHub token with 'repo' scope: /settings/connections
```

With `--json`, this arrives as a parseable contract on stdout:

```json theme={null}
{
  "error": "credential_required",
  "provider": "github",
  "required_scope": "repo",
  "connect_url": "/settings/connections"
}
```

A private repository sync found no usable GitHub credential for you.

Signing in with GitHub grants public access only. Private repositories need a personal access token with the `repo` scope, connected under **Settings → Connections**. See [Connect GitHub for private repos](/guides/connect-github-private-repos).

Because the contract is machine-readable, a script can branch on it:

```bash theme={null}
if ! out=$(jstm skills repo sync 9b74e2a1-… --json 2>/dev/null); then
  echo "$out" | jq -e '.error == "credential_required"' >/dev/null && echo "connect GitHub first"
fi
```

## Repository not found, after connecting

GitHub returns the same "not found" response for a private repository whether it doesn't exist or you can't see it. So once you have a credential connected and a sync still fails, there are two possibilities and the message names both:

1. The repository path is wrong. Check the URL.
2. Your token lacks `repo` access to that repository. Check the token's scopes.

For organization repositories protected by SSO, authorize the token for that organization's SSO and retry. A token with the right scope still can't read an SSO-protected repository until it's authorized for that org.

## The agent is using the wrong account

The usual cause is a personal credential shadowing a shared one. Credentials resolve from the most specific tier outward — personal, then workspace, then org — so a personal GitHub token wins over the team's.

Look at the actual resolution:

```bash theme={null}
jstm connection resolve github --workspace acme-corp/finance
```

This prints the tier-by-tier walk and shows what matched where. If a personal credential is winning and shouldn't be, remove it:

```bash theme={null}
jstm connection remove github --workspace acme-corp/finance --id 4d90c7e2-…
```

## The credential exists but doesn't work

A listing shows a credential is present. It doesn't show whether it still works.

```bash theme={null}
jstm connection test slack --workspace acme-corp/finance
```

This calls the provider for real, which catches an expired, revoked, or rotated token.

Credentials also carry a status — `ACTIVE`, `NEEDS_REAUTH`, or `REVOKED` — visible in `jstm vault audit`.

## A credential is missing for a skill

A skill declares the services it requires. If one has no credential, the run stops and names the provider rather than guessing.

```bash theme={null}
jstm skills check google-calendar-read
jstm agent readiness failed-payment-digest
```

`readiness` reports blockers and exits non-zero when there are any. Many have a targeted fix:

```bash theme={null}
jstm agent readiness-fix failed-payment-digest --action fix-credential
```

## A team can't see an org credential

Org credentials have a scope. A credential set to Selected workspaces is only available to the workspaces named.

```bash theme={null}
jstm vault grants 7ac1d3f5-… 4d90c7e2-…      # current scope
jstm vault audit --org acme-corp             # everything, grouped by scope
```

To widen it:

```bash theme={null}
jstm vault scope 4d90c7e2-… --scope all
jstm vault scope 4d90c7e2-… --scope selected \
  --workspace acme-corp/finance --workspace acme-corp/revops
```

Both require org owner or admin. Only org-vault credentials are scopeable — scoping a workspace or personal credential is rejected.

## Selected workspaces without a workspace

```bash theme={null}
jstm vault scope 4d90c7e2-… --scope selected
```

This fails locally with exit `1` and sends nothing, because an empty restriction is meaningless. Name at least one workspace with repeatable `--workspace`.

## An MCP server's tools are empty

Registering an endpoint succeeds even before a key is attached — it registers with an empty tool list. Attach the key, which introspects automatically:

```bash theme={null}
jstm mcp connect-key endpoint/acme-corp-finance/ledger-tools --api-key <key>
```

If the list is still empty after a successful attach, the key most likely lacks permission for the tools you expect. Re-introspect after fixing it:

```bash theme={null}
jstm mcp introspect endpoint/acme-corp-finance/ledger-tools
```

If the server applies the key somewhere other than a bearer token:

```bash theme={null}
jstm mcp connect-key endpoint/acme-corp-finance/ledger-tools \
  --api-key <key> --auth-scheme header --auth-name X-API-Key
```

## A connector fails with no environment variable

An MCP server reads its credential from an environment variable whose name the server dictates. JoyStream resolves that name from the server's manifest first, then from a curated provider overlay. If neither matches, it fails with an error naming the service rather than guessing.

A server declaring more than one secret variable also fails, deliberately — JoyStream won't choose which one gets the token.

See [Credentials and vaults](/features/credentials-and-vaults).

## Tokens never appear in output

No command prints a credential's value. `vault audit`, `vault show`, and `vault grants` return metadata only. Sync errors are written so they can't echo a token back.

The CLI has no `--token` flag by design, so a token never lands in your shell history.

## See also

* [Credentials and vaults](/features/credentials-and-vaults)
* [Connect a service](/guides/connect-a-service)
* [`jstm connection`](/cli/connection) and [`jstm vault`](/cli/vault)
