{"record":{"id":"8be562223555fed3","repo":"hashicorp/terraform","slug":"error-asking-s-v-8be562","errorCode":null,"errorMessage":"Error asking %s: %v","messagePattern":"Error asking (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/cloud/backend_common.go","lineNumber":507,"sourceCode":"\n\t\t\t\t\tif err == errRunDiscarded {\n\t\t\t\t\t\terr = errApplyDiscarded\n\t\t\t\t\t\tif op.PlanMode == plans.DestroyMode {\n\t\t\t\t\t\t\terr = errDestroyDiscarded\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tresult <- err\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}()\n\n\tresult <- func() error {\n\t\tv, err := op.UIIn.Input(doneCtx, opts)\n\t\tif err != nil && err != context.Canceled && stopCtx.Err() != context.Canceled {\n\t\t\treturn fmt.Errorf(\"Error asking %s: %v\", opts.Id, err)\n\t\t}\n\n\t\t// We return the error of our parent channel as we don't\n\t\t// care about the error of the doneCtx which is only used\n\t\t// within this function. So if the doneCtx was canceled\n\t\t// because stopCtx was canceled, this will properly return\n\t\t// a context.Canceled error and otherwise it returns nil.\n\t\tif doneCtx.Err() == context.Canceled || stopCtx.Err() == context.Canceled {\n\t\t\treturn stopCtx.Err()\n\t\t}\n\n\t\t// Make sure we cancel the context here so the loop that\n\t\t// checks for external changes to the run is ended before\n\t\t// we start to make changes ourselves.\n\t\tcancel()\n\n\t\tif v != keyword {\n\t\t\t// Retrieve the run again to get its current status.","sourceCodeStart":489,"sourceCodeEnd":525,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/cloud/backend_common.go#L489-L525","documentation":"Inside the confirm() goroutine, op.UIIn.Input returned an error that is neither context.Canceled on the done context nor on stopCtx. The backend reports which input id failed ('override', 'approve', etc.) plus the wrapped error.","triggerScenarios":"op.UIIn.Input(doneCtx, opts) returns non-nil, non-canceled err: stdin closed unexpectedly; terminal read failure; input implementation raised an internal error; EOF from a piped/non-interactive stdin.","commonSituations":"Running an interactive apply inside CI without a TTY; SSH session dropped mid-prompt; stdin redirected from /dev/null or a closed pipe; custom UIIn implementation threw.","solutions":["Provide a real TTY for interactive ops, or use --auto-approve to bypass prompts.","Ensure stdin is not redirected from /dev/null when prompts are expected.","For custom UIIn implementations, make Input return context.Canceled on shutdown rather than a raw error.","Reconnect (e.g. re-attach to tmux/SSH) if the session dropped."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"func interactiveInputAvailable(op *backendrun.Operation) bool {\n    return op.UIIn != nil && op.UIOut != nil && isTerminal(os.Stdin)\n}\n// skip prompts in CI: pass --auto-approve","typeGuard":"func isTerminal(f *os.File) bool {\n    fi, err := f.Stat()\n    return err == nil && (fi.Mode()&os.ModeCharDevice) != 0\n}","tryCatchPattern":"v, err := op.UIIn.Input(ctx, opts)\nif err != nil && err != context.Canceled && ctx.Err() != context.Canceled {\n    // treat as non-fatal: fall back to default or fail gracefully\n    return fallback(opts)\n}","preventionTips":["Provide a real TTY for interactive ops; use --auto-approve in CI.","Do not redirect stdin from /dev/null when prompts are expected.","Custom UIIn implementations should return context.Canceled on shutdown."],"tags":["tfe","hcp","cloud-backend","interactive","input","tty"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}