Repository navigation
feat(pass): hint how to fix a failed connection to the secrets engine - #678
Merged
Merged
Conversation
docker-agent
reviewed
Oct 8, 2026
docker-agent
left a comment
Contributor
There was a problem hiding this comment.
Assessment: 🟢 APPROVE
Lower-confidence findings (not posted inline)
The following low-severity observations were noted by the drafter. They did not reach the threshold for inline comments (all are low severity; verification was skipped per policy).
- [low]
plugins/pass/commands/client.go:37 —wrapEngineErrorswraps onlyRunE, unlikewrapKeychainErrorswhich also wrapsPreRunE(no current impact — none of the callers usePreRunEtoday, but a future command withPreRunEwould silently miss the engine hint) - [low / security]
plugins/pass/commands/client.go:61 — unsanitisedce.SocketPathinterpolated directly into the user-visible hint string; a path with embedded newlines or control characters could corrupt the output (considerfmt.Sprintf("%q", socket)) - [low]
plugins/pass/commands/client.go:37 —wrapEngineErrorssilently no-ops whencmd.RunEis nil (command usesRuninstead); no current callers are affected, but aRun-only command would receive no hint
Benehiko
force-pushed
the
feat/client-engine-not-running
branch
from
October 8, 2026 08:53
2ae84e2 to
74d43ee
Compare
Benehiko
force-pushed
the
feat/pass-engine-hints
branch
from
October 8, 2026 09:12
d5a2b8a to
b32c24f
Compare
Benehiko
force-pushed
the
feat/client-engine-not-running
branch
3 times, most recently
from
October 8, 2026 12:33
04a51ec to
fadde1c
Compare
Benehiko
force-pushed
the
feat/pass-engine-hints
branch
from
October 8, 2026 12:40
b32c24f to
0b63bb3
Compare
joe0BAB
reviewed
Oct 8, 2026
joe0BAB
reviewed
Oct 8, 2026
joe0BAB
reviewed
Oct 8, 2026
get --reveal, rm and run now append a hint to a client.ConnectError, based on its reason: start the engine when it is not running, restart it when it does not respond, and check access to the socket when permission is denied. The not-running and timeout hints name Docker Desktop only when the socket is Docker Desktop's; for any other socket, such as a standalone engine, they name the socket instead. Unknown reasons and other errors pass through unchanged, as with the keychain hints. Signed-off-by: Alano Terblanche <18033717+Benehiko@users.noreply.github.com>
Benehiko
force-pushed
the
feat/pass-engine-hints
branch
from
October 8, 2026 12:55
0b63bb3 to
4d604e3
Compare
Tell the Docker Desktop, standalone and custom sockets apart: the not-running and timeout hints now name the standalone secrets engine when the socket is api.StandaloneSocketPath(), and keep the generic wording for any other socket. Address review feedback: reword the permission hint to say the user lacks permission to connect and needs read and write access to the socket, quote the socket path so control characters cannot corrupt the output, and wrap PreRunE as well as RunE, as the keychain hints do. Signed-off-by: Alano Terblanche <18033717+Benehiko@users.noreply.github.com>
Add ConnectError.Hint, which returns a one-line suggestion for fixing a failed connection based on its reason and socket: Docker Desktop's socket, the standalone engine's socket, or a custom one. Every SDK consumer can now show the same hints, and Error() is unchanged, so callers choose whether to print them. pass's withEngineHint now only finds the ConnectError and appends its hint. The per-reason wording tests move to the client package. Signed-off-by: Alano Terblanche <18033717+Benehiko@users.noreply.github.com>
Signed-off-by: Alano Terblanche <18033717+Benehiko@users.noreply.github.com>
Signed-off-by: Alano Terblanche <18033717+Benehiko@users.noreply.github.com>
Benehiko
enabled auto-merge
October 8, 2026 13:31
joe0BAB
reviewed
Oct 8, 2026
| permissionDeniedHint = "Your user lacks permission to connect to %s. Grant it read and write access to the socket and retry." | ||
| ) | ||
|
|
||
| // Hint returns a user friendly message to help recover from the error. |
joe0BAB
approved these changes
Oct 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
#677 gives the client a
ConnectErrorthat says why it could not reach the engine. Until now, pass printed a bare dial error, which tells a user nothing about what to do next.What
ConnectError.Hint()method in the client returns a user friendly message to help recover from the error. Every SDK consumer can show the same wording.Error()is unchanged, so callers choose whether to print the hint.get --reveal,rmandrunprint that hint below the error.The hint depends on
ConnectError.Reasonand on which socket failed. The secrets engine can run inside Docker Desktop or standalone, so the not-running and timeout hints are worded for the engine that listens on that socket:api.DesktopSocketPath().api.StandaloneSocketPath().WithSocketPath.ReasonNotRunning"<socket path>"."<socket path>".ReasonTimeout"<socket path>"did not respond. Restart it and retry."<socket path>"did not respond. Restart it and retry.ReasonPermissionDenied"<socket path>". Grant it read and write access to the socket and retry.ReasonUnknownHint()returns""; pass leaves the error unchangedThe socket path is quoted, so control characters in it cannot corrupt the output. If the error carries no socket path,
"<socket path>"reads "the secrets engine socket".Example, with the default (Docker Desktop) socket:
Hint()compares the cleaned socket path withapi.DesktopSocketPath()andapi.StandaloneSocketPath().wrapEngineErrors/withEngineHintpair that mirrors the existingwrapKeychainErrors/withKeychainHint. It finds theConnectErrorin the chain and appends its hint in the same\n\n<hint>format, and it wraps bothPreRunEandRunE.errors.Is(err, client.ErrSecretsEngineNotRunning)still matches.rm: hints still appear when the connection error is joined with per-secret "not found" errors.Notes
plugins/passbuilds against the local client through areplacedirective, but itsgo.modrequiresclient v0.1.2. Building pass outside this repo needs a client release that includesHint(), followed by a bump in pass.ConnectErrorit builds has no socket path, so the hint uses the custom-socket wording with "the secrets engine socket". This behaviour predates this PR.Tests
client.TestConnectErrorHintcovers the wording:ReasonUnknowncommands.TestWithEngineHintcovers how pass applies it:errors.Joinnil,ReasonUnknown,ErrAccessDenied)get --revealandrmtests against a missing socket now check that the custom-socket hint, with that socket's quoted path, is printed.go vet(darwin, linux, windows) andgolangci-lintare clean, and theclientandplugins/passtests pass on macOS. I have not run this PR on Windows; feat(client)!: report why the client could not connect to the engine #677 covers the Windows classification.Closes docker/secrets-engine-private#729.