DeepSeek Harness headless MISSING_CREDENTIAL: .env

TroubleshootingPublished 2026-10-30Author: DeepSeek Plugin Market
DeepSeek HarnessDSHheadlessMISSING_CREDENTIALcredentials.envtoken revocation
DeepSeek Harness headless reports MISSING_CREDENTIAL although the key is in .credentials.yaml. Since 0.2.1-alpha.3 it only reads the launch env and .env files.

The key sits in refs inside ~/.dsh/.credentials.yaml, with the real value inline, yet dsh --profile headless "hi" exits after a second with MISSING_CREDENTIAL: llm-pi-ai: no credential for provider route "zai-coding-cn". The key is not malformed; since 0.2.1-alpha.3 the bundled headless profile does not mount the credential service at all, and the whole source list changed (#11051). Identify the environment first, then the version, then pick a path.

DeepSeek Harness: Step 1: identify the environment — desktop working does not mean headless works

The desktop app reads the credential store; headless does not. The same key has completely different fates on the two sides, so confirm which one you are running.

  1. Look at the launch command: --profile headless, or anything pulled up by a scheduler as dsh headless, is headless.
  2. Look for a UI: the desktop app has a web UI and a "Models" settings page; headless has only stdout and NDJSON.
  3. Look at the error shape: headless prints dsh: <CODE>: ... and exits on one line, while the desktop app shows a card in the UI.
  4. If you run it in a scheduler or CI, treat it as headless by default.

This step has exactly one conclusion: do not carry over the desktop experience of "filling in a key on the models page is enough" to headless.

DSH plugin: Step 2: identify the version — 0.2.1-alpha.3 is the dividing line

This is a documented design change, not a regression: 0.2.0-rc.2 resolves stored credentials, and from 0.2.1-alpha.3 the bundled headless profile disables the related services.

  1. Run dsh --version and record the full version.
  2. Below 0.2.1-alpha.3, investigate the old behavior first.
  3. At 0.2.1-alpha.3 and later, treat storage as not working and stop spending time validating the .credentials.yaml format.
  4. Also read the profile's cordis.patch.yml once; it explicitly lists credentials, authorization, and deepseek-account as disabled.

The community also observed that 0.2.1's first headless launch rewrites .credentials.yaml into the refs/records structure, so a changed file mtime does not mean you edited the right place.

DeepSeek Harness: The headless credential lookup order has only three places

Launch environment → the calling directory's .env → the Harness home .env, and nowhere else; the credential store is not among them.

  1. First priority is process environment variables, the env at the moment you launch.
  2. Second is .env in the current working directory.
  3. Third is ~/.dsh/.env (or the .env under DSH_HOME).
  4. Only when all three are empty does it throw MISSING_CREDENTIAL, and that failure happens before contacting the model endpoint — so network, proxy, and balance are not the cause.
bash
# ~/.dsh/.env (variable names follow the profile's refs)
ZAI_CODING_CN_API_KEY=sk-xxxxxxxx

The community ran an isolation comparison: headless with only a stored key sent no request at all, while exporting a fake key, the calling directory .env, the home .env, and the three-line patch all worked and the mock received the corresponding key. In the control group, SDK and ACP worked with only the stored key because their credential service is active.

DSH Plugin: Two workable paths: write .env or restore the services

The simplest is putting the key into ~/.dsh/.env; to keep using the credential store, add the services back with the README's three-line patch.

  1. Path A: write ZAI_CODING_CN_API_KEY=<real key> into ~/.dsh/.env, making sure the variable name matches the profile's refs reference.
  2. Tighten the file permissions; do not leave it world-readable.
  3. Run dsh --profile headless "hi" again and see whether MISSING_CREDENTIAL is gone.
  4. Path B: open packages/bundle/headless/README.md and add the documented three-line restore patch to your profile config.
  5. Restart and run once more to verify credentials resolve from storage.
  6. If you use a scheduler such as LaunchAgent, put the key into its EnvironmentVariables too, or interactive terminals will work while scheduled jobs keep failing.

In the community case a production cron failed twice at 07:30 and 09:00 on 10-23 and only recovered after the scheduler environment was injected.

DeepSeek Harness: The error message itself misleads you

The MISSING_CREDENTIAL text does not branch by plane: it first recommends "save it to the credential service (the web models page writes it there)", exactly the service headless does not mount.

  1. The source shows the resolver first calls ctx.get('credentials') to decide whether to query storage or the launch environment.
  2. But the error text is three hardcoded sentences that do not follow that branch.
  3. The result is a user following the first suggestion and hitting the same error again.
  4. What actually works is the third sentence, "export it in the launch environment" — the community notes it was always there, just buried by the first two.
  5. This is a diagnostic wording defect, low severity, but it is not "credentials lost" and carries no privilege risk.

DSH plugin: Side scenario: revoking browser session tokens globally

Browser cookies on the desktop web side survive ordinary restarts, so global revocation requires deleting the single client-connection/browser-session record and restarting.

  1. Fully stop every Harness process using the same home.
  2. Back up .credentials.yaml (default %USERPROFILE%\.dsh\.credentials.yaml; use the actual path if DSH_HOME changed).
  3. Under records, delete only the client-connection/browser-session key and its entire value, keeping version, refs, and other records; if it was the last one, leave records: {}.
  4. Restart Harness and sign in again with the freshly generated launch URL.
  5. Verify: an old cookie, without ?token=, against the same scheme/host/port should return 401.
  6. A request with the new launch URL should return 303, and authentication with its new cookie should return 200.

One trap: the authority must match exactly. If you change hostname or port the cookie is invalid anyway, and you will mistakenly believe revocation worked. The community verified in an isolated environment that an old cookie still works after an ordinary restart, and is only rejected after that record is deleted and the app restarted.

Cautions

Check the plane and the version before editing any credential file.

  1. Do not edit only .credentials.yaml and expect headless to pick it up. It reads .env and environment variables.
  2. Do not use SDK / ACP behavior as the reference. Their credential service is active, so the prompt applies to them.
  3. Do not ignore the scheduler environment. Working in an interactive terminal does not mean a cron job works.
  4. Do not delete the whole credential file to revoke a token. Delete only that one record; other references are unaffected.
  5. Record the version number. It is the only basis for deciding "design change or defect".

If your error code is 401/403 rather than MISSING_CREDENTIAL, that is a different chain — check the credential contents and account status first.See Fix DSH API key errors: MISSING_CREDENTIAL and UNKNOWN_MODEL for the related case.

FAQ

Why does DeepSeek Harness headless report MISSING_CREDENTIAL when .credentials.yaml clearly contains the key?

DeepSeek Harness never reads stored credentials under headless because the bundled headless profile disables the credentials, authorization, and deepseek-account services. It only checks the launch environment, the calling directory's .env, and ~/.dsh/.env, so putting the key in ~/.dsh/.env is what works.

From which DeepSeek Harness version does headless stop reading the credential store?

DeepSeek Harness stopped reading the credential store from 0.2.1-alpha.3 according to the community reply, a documented change rather than a regression. The same config resolves fine on 0.2.0-rc.2, and after upgrading only the launch environment remains.

MISSING_CREDENTIAL in DeepSeek Harness tells me to save the key to the credential service, so why does that still fail?

Saving the key to the credential service still fails because the DeepSeek Harness error text does not branch by plane. The code already checks with ctx.get('credentials') whether the service exists, but the text still recommends a service headless does not mount; the only useful line is the third one, export it in the launch environment.

How do I restore stored credentials in DeepSeek Harness without changing the profile?

The DeepSeek Harness fix is the three-line patch in packages/bundle/headless/README.md, which adds the credential services back without changing the profile. The community verified four working sources: exported environment variable, calling directory .env, ~/.dsh/.env, and the three-line restore patch.

How do I revoke DeepSeek Harness browser session cookies globally when the UI has no entry for it?

To revoke browser session cookies globally, stop all DeepSeek Harness processes, back up .credentials.yaml, delete only client-connection/browser-session under records, and restart. An old cookie without ?token= against the same authority should then return 401.

Related Terms

MISSING_CREDENTIAL
MISSING_CREDENTIAL is the error code DeepSeek Harness returns when it cannot resolve model credentials, failing fast with exit 1 under headless. It means the credential source is unavailable in the current combination, not that the key itself is wrong.— https://github.com/deepseek-ai/deepseek-harness/discussions/11051
headless profile
The headless profile is the bundled profile for running DeepSeek Harness without a UI, whose cordis.patch.yml disables the credentials, authorization, and deepseek-account services by default. Credentials can only come from the launch environment or .env files.— https://github.com/deepseek-ai/deepseek-harness/discussions/10609
launch environment
The launch environment is the set of environment variables the dsh process inherits at startup, and it is the highest-priority credential source under headless. It ranks ahead of the calling directory's .env and the Harness home .env.— https://github.com/deepseek-ai/deepseek-harness/discussions/10609
client-connection/browser-session
client-connection/browser-session is the record key in the local credential store that holds a browser session token. Deleting that record and restarting revokes all issued session cookies without affecting other credential records.— https://github.com/deepseek-ai/deepseek-harness/discussions/10915

Sources