{"record":{"id":"43f6496b0d5d1e76","repo":"FiloSottile/age","slug":"client-failed-to-request-confirmation","errorCode":null,"errorMessage":"client failed to request confirmation","messagePattern":"client failed to request confirmation","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/plugin.go","lineNumber":567,"sourceCode":"// selected the yes or no option. Confirm returns an error if the client can't\n// request the confirmation.\n//\n// It must only be called by a Wrap or Unwrap method invoked by [Plugin.Main].\nfunc (p *Plugin) Confirm(prompt, yes, no string) (choseYes bool, err error) {\n\targs := []string{format.EncodeToString([]byte(yes))}\n\tif no != \"\" {\n\t\targs = append(args, format.EncodeToString([]byte(no)))\n\t}\n\ts := &format.Stanza{Type: \"confirm\", Args: args, Body: []byte(prompt)}\n\tif err := s.Marshal(p.stdout); err != nil {\n\t\treturn false, p.fatalInteractf(\"failed to write confirm stanza: %v\", err)\n\t}\n\ts, err = readOkOrFail(p.sr)\n\tif err != nil {\n\t\treturn false, p.fatalInteractf(\"%v\", err)\n\t}\n\tif s.Type == \"fail\" {\n\t\treturn false, fmt.Errorf(\"client failed to request confirmation\")\n\t}\n\tif err := expectStanzaWithNoBody(s, 1); err != nil {\n\t\treturn false, p.fatalInteractf(\"%v\", err)\n\t}\n\treturn s.Args[0] == \"yes\", nil\n}\n\n// fatalInteractf prints the error to stderr and sets the broken flag, so the\n// Wrap/Unwrap caller can exit with an error.\nfunc (p *Plugin) fatalInteractf(format string, args ...any) error {\n\tp.broken = true\n\tfmt.Fprintf(p.stderr, format, args...)\n\treturn fmt.Errorf(format, args...)\n}\n\nfunc (p *Plugin) fatalf(format string, args ...any) int {\n\tfmt.Fprintf(p.stderr, format, args...)\n\treturn 1","sourceCodeStart":549,"sourceCodeEnd":585,"githubUrl":"https://github.com/FiloSottile/age/blob/b74dce4cdbe35b5e5f66c06d9612b72f89028758/plugin/plugin.go#L549-L585","documentation":"Confirm asks the age client to display a yes/no confirmation to the user via the confirm protocol command. This error means the client responded with a \"fail\" stanza — it could not present the confirmation or obtain an answer, so the plugin cannot know the user's choice.","triggerScenarios":"The client has no way to show a yes/no dialog (headless run, unsupported client version); the client refuses the confirm request; the interaction channel is in a state where the client returns fail.","commonSituations":"Hardware-token plugins asking \"touch your key / insert device\" during CI or SSH sessions without an agent UI; older age clients lacking confirm support; scripting age where all UI is suppressed.","solutions":["Proceed with a safe default or let the operation fail explicitly when the confirmation cannot be shown, depending on security requirements","Run the workflow in an interactive environment where the client UI can confirm","Upgrade the age client to one that supports the confirm command"],"exampleFix":"// before\nok, err := p.Confirm(\"touch device\", \"proceed without touch?\")\nif err != nil { return err }\n// after\nok, err := p.Confirm(\"touch device\", \"proceed without touch?\")\nif err != nil {\n    return fmt.Errorf(\"cannot confirm user intent: %w\", err) // fail closed\n}","handlingStrategy":"fallback","validationCode":"// Only call Confirm when an interactive client is available:\n// if !interactiveSession { use safe default instead of Confirm }","typeGuard":null,"tryCatchPattern":"ok, err := p.Confirm(question, fallbackQuestion)\nif err != nil {\n    // fail closed or apply documented default\n    return fmt.Errorf(\"confirmation unavailable: %w\", err)\n}","preventionTips":["Decide and document fail-open vs fail-closed behavior for missing confirmations","Avoid GUI-dependent plugins in headless jobs","Upgrade age clients to support the confirm command"],"tags":["age","plugin","confirm","client-interaction"],"backgroundTag":"plugin-client-interaction-failed","analyzedSha":"b74dce4cdbe35b5e5f66c06d9612b72f89028758","analyzedAt":"2026-08-31T23:59:31.627Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}