Bug description
The skills API client uses a fixed 30-second HTTP timeout with no CLI flag or environment override. Operations that legitimately exceed it — notably thv skill install pulling a large OCI artifact for the first time — fail with a message that blames server availability, when the server is healthy and still doing the work.
https://github.com/stacklok/toolhive/blob/main/pkg/skills/client/client.go#L29
defaultTimeout = 30 * time.Second
WithTimeout exists as a library option but is not reachable from the CLI: newSkillClient calls skillclient.NewDefaultClient(ctx) with no options.
Steps to reproduce
TOOLHIVE_SKILLS_LOCK_ENABLED=true thv serve &
# any skill whose artifact takes >30s to pull on the current connection
thv skill install ghcr.io/stacklok/dockyard/skills/yara-rule-authoring:0.1.0 \
--scope project --project-root "$PWD" --clients claude-code
Expected behavior
Either the timeout accommodates long-running pulls, or it is configurable, or the error distinguishes "the request timed out" from "the server is unreachable".
Actual behavior
Error: failed to install skill: could not reach ToolHive API server — is 'thv serve' running?: Post "http://127.0.0.1:8080/api/v1beta/skills": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
Hint: ensure 'thv serve' is running
The server is running and unaffected; it logs the client hanging up mid-operation:
ERROR internal server error error="checking existing skill: scanning skill row: context canceled"
The hint sends users to check something that is not the problem. Retrying does not help, because the timeout is shorter than the operation regardless of warm caches.
Suggested fix
Some combination of:
- treat
context deadline exceeded separately from connection failures in formatSkillError, so the message says the operation timed out;
- allow an override (a
--timeout flag, or an env var read by NewDefaultClient);
- consider a longer default for pull-backed operations, which are inherently network-bound and unbounded in size.
Environment
- OS/version: macOS 15 (arm64)
- ToolHive version: v0.42.0
Additional context
The same artifact pulls comfortably inside 30s on GitHub-hosted runners, so this reproduces based on connection speed and artifact size rather than deterministically.
Bug description
The skills API client uses a fixed 30-second HTTP timeout with no CLI flag or environment override. Operations that legitimately exceed it — notably
thv skill installpulling a large OCI artifact for the first time — fail with a message that blames server availability, when the server is healthy and still doing the work.https://github.com/stacklok/toolhive/blob/main/pkg/skills/client/client.go#L29
WithTimeoutexists as a library option but is not reachable from the CLI:newSkillClientcallsskillclient.NewDefaultClient(ctx)with no options.Steps to reproduce
Expected behavior
Either the timeout accommodates long-running pulls, or it is configurable, or the error distinguishes "the request timed out" from "the server is unreachable".
Actual behavior
The server is running and unaffected; it logs the client hanging up mid-operation:
The hint sends users to check something that is not the problem. Retrying does not help, because the timeout is shorter than the operation regardless of warm caches.
Suggested fix
Some combination of:
context deadline exceededseparately from connection failures informatSkillError, so the message says the operation timed out;--timeoutflag, or an env var read byNewDefaultClient);Environment
Additional context
The same artifact pulls comfortably inside 30s on GitHub-hosted runners, so this reproduces based on connection speed and artifact size rather than deterministically.