Hmbown/CodeWhale · error · anyhow::Error
DeepSeek Harness import requires a dsh_cli grant, not {}
Error message
DeepSeek Harness import requires a dsh_cli grant, not {} What it means
Thrown by deepseek_api_key_from_grant when the supplied ExternalCredentialReadGrant's source is not ExternalCredentialSource::DshCli. The DeepSeek Harness import path only consumes dsh-credentials documents; grants pointing at other credential stores are rejected before any file I/O happens.
Source
Thrown at crates/tui/src/dsh_credentials.rs:18
//! Read-only DeepSeek Harness credential import.
//!
//! Official `dsh` stores API keys as a YAML mapping in
//! `$DSH_HOME/.credentials.yaml`. Codewhale may read `DEEPSEEK_API_KEY` from
//! that exact file only after `codewhale auth external-consent`. The file is
//! never written, refreshed, or loaded into the process environment.
use anyhow::{Result, bail};
use codewhale_config::ExternalCredentialReadGrant;
const DEEPSEEK_API_KEY_REF: &str = "DEEPSEEK_API_KEY";
/// Extract the DeepSeek API key from a granted dsh credentials document.
pub(crate) fn deepseek_api_key_from_grant(
grant: &ExternalCredentialReadGrant,
) -> Result<Option<String>> {
if grant.source() != codewhale_config::ExternalCredentialSource::DshCli {
bail!(
"DeepSeek Harness import requires a dsh_cli grant, not {}",
grant.source().as_str()
);
}
let Some(text) = crate::external_credentials::read_to_string(grant)? else {
return Ok(None);
};
parse_dsh_deepseek_api_key(&text)
}
/// Strict subset of dsh-credentials-local: a mapping of POSIX identifiers to
/// non-empty strings. Nested values, empty strings, and duplicate keys fail
/// closed. Only `DEEPSEEK_API_KEY` is returned.
pub(crate) fn parse_dsh_deepseek_api_key(text: &str) -> Result<Option<String>> {
let mut found = None;
let mut seen = std::collections::BTreeSet::new();
for (index, raw) in text.lines().enumerate() {
let line = raw.trim();View on GitHub (pinned to 0c42157ee5)
Solutions
- Construct the grant from the dsh credentials store so grant.source() is DshCli
- Route non-dsh credential sources through their own readers instead of this function
- Check grant.source().as_str() before calling if the source can vary
Example fix
// before let grant = ExternalCredentialReadGrant::new(path, ExternalCredentialSource::EnvFile); let key = dsh_credentials::deepseek_api_key_from_grant(&grant)?; // after let grant = ExternalCredentialReadGrant::new(path, ExternalCredentialSource::DshCli); let key = dsh_credentials::deepseek_api_key_from_grant(&grant)?;
Defensive patterns
Strategy: validation
Validate before calling
use codewhale_config::{ExternalCredentialReadGrant, ExternalCredentialSource};
fn import_deepseek(grant: &ExternalCredentialReadGrant) -> Result<Option<String>> {
if grant.source() != ExternalCredentialSource::DshCli {
return Err(anyhow::anyhow!(
"refusing import: grant source is {} but this path requires dsh_cli",
grant.source().as_str()
));
}
dsh_credentials::deepseek_api_key_from_grant(grant)
} Type guard
fn is_dsh_grant(grant: &ExternalCredentialReadGrant) -> bool {
grant.source() == codewhale_config::ExternalCredentialSource::DshCli
} Prevention
- Construct grants with the source fixed at creation so the type carries the provenance
- Keep one import function per credential source instead of a generic dispatcher
- Assert the source in tests for every import path so wiring regressions fail early
When it happens
Trigger: Passing a grant created for a different source (any codewhale_config::ExternalCredentialSource variant other than DshCli) into deepseek_api_key_from_grant.
Common situations: Wiring the import to the wrong credential store after refactoring grant plumbing; a caller reusing a generic grant helper without setting the source.
Related errors
- DeepSeek Harness credentials line {} is not `KEY: value`
- DeepSeek Harness credentials line {} has a non-identifier ke
- DeepSeek Harness credentials declare `{key}` more than once
- DeepSeek Harness credentials line {} has an empty value
- external {} credential file {} exceeds the {} byte safety li
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/9b5092d2cddc3c37.
Report an issue: GitHub.