gitbutlerapp/gitbutler · error
When using OpenAI in a bring your own key configuration, you
Error message
When using OpenAI in a bring your own key configuration, you must provide a valid token
What it means
Raised in the hunk-discard path after the new worktree content is reconstructed: it stats the path (no symlink following) and requires a regular file, because the result must be run through the filter pipeline and written back as file content. If the path is now a directory, symlink, or otherwise not a plain file, the operation bails rather than corrupt it.
Source
Thrown at apps/desktop/src/lib/ai/service.ts:343
if (modelKind === ModelKind.LMStudio) {
const lmStudioEndpoint = await this.getLMStudioEndpoint();
const lmStudioModelName = await this.getLMStudioModelName();
if (!lmStudioEndpoint) {
throw new Error("When using LM Studio, you must provide a valid endpoint");
}
return new LMStudioClient(lmStudioEndpoint, lmStudioModelName);
}
if (modelKind === ModelKind.OpenAI) {
const openAIModelName = await this.getOpenAIModelName();
const openAIKey = await this.getOpenAIKey();
const openAICustomEndpoint = await this.getOpenAICustomEndpoint();
if (!openAIKey) {
throw new Error(
"When using OpenAI in a bring your own key configuration, you must provide a valid token",
);
}
return new OpenAIClient(openAIKey, openAIModelName, openAICustomEndpoint);
}
if (modelKind === ModelKind.Anthropic) {
const anthropicModelName = await this.getAnthropicModelName();
const anthropicKey = await this.getAnthropicKey();
if (!anthropicKey) {
throw new Error(
"When using Anthropic in a bring your own key configuration, you must provide a valid token",
);
}
return new AnthropicAIClient(anthropicKey, anthropicModelName);View on GitHub (pinned to caf1f223d3)
Solutions
- Re-run worktree_changes and rebuild the discard specs so the current on-disk kind is reflected
- Use whole-file discard (empty hunk_headers), which handles restores of symlinks and other kinds
- Stop the concurrent writer (build watcher, sync client) that replaced the path, then retry
- If the symlink/dir is intended, discard it as a whole file instead of by hunks
Defensive patterns
Strategy: validation
Validate before calling
let wt = but_core::diff::worktree_changes(repo)?; // refresh right before the call
// and immediately before discarding, confirm the path is still a regular file:
let p = repo.workdir().unwrap().join(rela_path);
if let Ok(md) = std::fs::symlink_metadata(&p) {
assert!(md.is_file(), "{} is no longer a regular file", p.display());
} Try / catch
if let Err(err) = discard_workspace_changes(repo, specs, ctx) {
if err.to_string().contains("invalid type") {
// re-run worktree_changes and rebuild specs; fall back to whole-file discard
} else { return Err(err); }
} Prevention
- Do not run discard while build tools/watchers may swap files for symlinks or directories
- Refresh the diff right before writing, keep the read-to-write window short
When it happens
Trigger: discard_workspace_changes with hunks for a path that, between the diff computation and the write, was replaced by a symlink or directory; or the change itself tracks a symlink/directory while hunks were supplied from stale data. gix::index::fs::Metadata::from_path_no_follow returning a non-file md triggers it.
Common situations: Concurrent processes (build tools, other agents, watchers) swapping files for symlinks or directories mid-operation; monorepo tooling creating dir-over-file; a diff computed before the swap and replayed after.
Related errors
- Invalid response: ${JSON.stringify(result)}
- Failed to communicate with LM Studio server: ${error instanc
- When using LM Studio, you must provide a valid endpoint
- When using GitButler's API to summarize code, you must be lo
- When using Anthropic in a bring your own key configuration,
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/8692d483f648c70d.
Report an issue: GitHub.