[BUG] Self-hosted runner: resuming a session fails to start when an add_repo'd repo uses Git LFS — smudge has no credentials for the session git proxy
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
On a self-hosted runner environment (environment_kind: byoc), resuming a session onto a fresh pod re-clones the session's repos — including repos attached mid-session via add_repo, which are not part of the session's initial source set. If such a repo uses Git LFS, the LFS smudge cannot obtain credentials for the session git proxy, and the session dies before it starts:
The session process failed to start.
The pack fetch itself succeeds — only the LFS smudge fails. git-lfs runs the smudge as its own process and resolves credentials through git credential, rather than inheriting whatever the fetch used. At that point in resume-time startup the credential helper the harness installs at /workspace/.runner/git-proxy-cred is not usable yet, so git-lfs gets nothing back, git falls through to prompting, prompts are disabled, and the smudge fails.
Because the harness's own ~/.gitconfig sets filter.lfs.required = true, a failed smudge is fatal rather than degrading to a pointer file — so the checkout aborts and startup never completes.
This is specific to the resume path. Mid-session, LFS works correctly: cloning the same repo through the same session git proxy resolved all 7 LFS objects and negotiated auth=basic, and the batch API answers 401 unauthenticated / 200 with the session token. So the proxy's LFS support is fine — this is a credential-availability bug in resume-time cloning that surfaces only on LFS repos, because they are the only ones needing a second, independently-authenticated request.
Two sessions hit this, one week apart, on the same pool. In both cases the workaround was to abandon the runner and teleport the session to a local executor.
What Should Happen?
Resume-time clones of add_repo'd repos should have working git credentials in place before checkout runs, so the LFS smudge can authenticate to the session git proxy. A session should not fail to start because an attached repo happens to use Git LFS.
Error Messages/Logs
The session process failed to start. You can try again by sending a new message or starting a new session.
Last output before exit:
git reset failed: fatal: could not read Username for 'https://api.anthropic.com': terminal prompts disabled
fatal: could not read Username for 'https://api.anthropic.com': terminal prompts disabled
error: external filter 'git-lfs filter-process' failed
fatal: path/to/data.jsonl: smudge filter lfs failed
fatal: could not read Username for 'https://api.anthropic.com': terminal prompts disabled
Downloading path/to/data.jsonl (74 KB)
fatal: could not read Username for 'https://api.anthropic.com': terminal prompts disabled
Error downloading object: path/to/data.jsonl (<oid>): Smudge error: Error downloading path/to/data.jsonl (<oid>): batch response: Git credentials for https://api.anthropic.com/v1/session_ingress/session/<session-id>/git_proxy/<org>/<repo>.git not found.
Errors logged to '/workspace/<org>/<repo>/.git/lfs/logs/20260827T152752.636004798.log'.
Use `git lfs logs last` to view the log.
error: external filter 'git-lfs filter-process' failed
fatal: path/to/data.jsonl: smudge filter lfs failed
Steps to Reproduce
- Start a session in a self-hosted runner environment (here a
ClaudeRunnerSetpool,<pool-name>, one pod per session). - Mid-session, attach a repository that Git-LFS-tracks files, using
add_repo. In our case<org>/<repo>, which trackspath/to/*.jsonlvia a.gitattributescontaining*.jsonl filter=lfs diff=lfs merge=lfs -text(7 objects, ~74 KB each). - Let the session go idle until it is released server-side (this pool is configured with
releaseIdleSessionMinutes: 10), so the next message resumes onto a fresh pod. - Resume the session by sending a message.
- The resume-time clone of the attached repo fails in the LFS smudge, and the session process never starts.
Note that a repo without LFS resumes fine, and the same LFS repo clones fine when done by hand during a live session — so the reproduction depends on the repo being both LFS-backed and attached via add_repo.
Diagnostic detail
Relevant config observed inside a session pod:
/home/claude/.gitconfig(harness-written, mtime ~3 min after pod start) contains both the credential helper and the LFS filter block:
````
[credential "https://api.anthropic.com"]
helper = !'/workspace/.runner/git-proxy-cred'
useHttpPath = false
username = unused
[filter "lfs"]
required = true
/workspace/.runner/git-proxy-credis a shell script that emits$CLAUDE_CODE_SESSION_ACCESS_TOKEN. Both it and~/.gitconfigare recreated per pod, which is why ordering against the resume-time clone matters.- Because
~/.gitconfigre-declaresfilter.lfs.required = true, it overrides the runner image's/etc/gitconfig, so the escalation-to-fatal cannot be softened from the image side.
Workaround, for anyone else hitting this: set GIT_LFS_SKIP_SMUDGE=1 in the pod environment. Checkout then writes pointer files, which needs neither network nor credentials, so the session starts; git lfs pull afterwards materialises the real content (verified to work with the variable still set). It has to be pod env — the failing checkout runs during harness startup, before any session wrapper exists.
Related, filed separately as anthropics/claude-code#90165: in a self-hosted session there is no insteadOf rewrite for https://github.com/..., so the clone command add_repo instructs you to run fails with fatal: could not read Username for 'https://github.com': No such device or address; the /v1/session_ingress/.../git_proxy/... URL must be substituted by hand.
Claude Model
Opus
Is this a regression?
I don't know
Claude Code Version
A custom self-hosted runner image (Ubuntu 26.04 arm64, git 2.53.0, git-lfs 3.7.1) tracking Anthropic's apt latest channel. 2.1.247 (Claude Code) on the local executor the session was teleported to.
Platform
Anthropic API
Operating System
Other Linux
[!NOTE] Repository, path, and pool names in this report are redacted placeholders (<org>/<repo>,path/to/...); the specifics are not relevant to the mechanism and can be shared privately if they would help triage.
---
Investigated and drafted by Claude Code; filed by the repository owner.