{"record":{"id":"8a9fab681023dfad","repo":"sipeed/picoclaw","slug":"failed-to-confirm-overwrite-w","errorCode":null,"errorMessage":"failed to confirm overwrite: %w","messagePattern":"failed to confirm overwrite: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/picoclaw/internal/mcp/add.go","lineNumber":49,"sourceCode":"\t\t\t}\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tcfg, err := loadConfig()\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tif cfg.Tools.MCP.Servers == nil {\n\t\t\t\tcfg.Tools.MCP.Servers = make(map[string]config.MCPServerConfig)\n\t\t\t}\n\n\t\t\tif _, exists := cfg.Tools.MCP.Servers[name]; exists && !opts.Force {\n\t\t\t\tvar overwrite bool\n\n\t\t\t\toverwrite, err = confirmOverwrite(cmd.InOrStdin(), cmd.OutOrStdout(), name)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"failed to confirm overwrite: %w\", err)\n\t\t\t\t}\n\t\t\t\tif !overwrite {\n\t\t\t\t\treturn fmt.Errorf(\"aborted: MCP server %q already exists\", name)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tserver, err := buildServerConfig(target, targetArgs, opts)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\n\t\t\tcfg.Tools.MCP.Enabled = true\n\t\t\tcfg.Tools.MCP.Servers[name] = server\n\n\t\t\tif err := saveValidatedConfig(cfg); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/cmd/picoclaw/internal/mcp/add.go#L31-L67","documentation":"When `picoclaw mcp add <name>` targets an existing server and --force is absent, the CLI prompts 'Overwrite? [y/N]' through confirmOverwrite(cmd.InOrStdin(), cmd.OutOrStdout(), name). This error wraps an I/O failure on those streams - not the answer itself. EOF on stdin is special-cased to a clean 'no' (error 149), but any other read/write error lands here.","triggerScenarios":"stdout piped to a reader that exits early (e.g. `picoclaw mcp add ... | head`), stdin a broken pipe, or the terminal gone. Quirk: pressing bare Enter makes fmt.Fscanln return 'unexpected newline', which surfaces as this error instead of a clean abort.","commonSituations":"Non-interactive scripts or CI piping output; SSH session dropped at the prompt; stdin from /dev/null combined with redirected stdout that fails.","solutions":["Use `--force` in scripts and CI to skip the prompt entirely","Do not pipe the command's stdout into an early-exiting reader while it may prompt","Run interactive adds in a real terminal; answer y, n, or Ctrl-C","If it fired on bare Enter, re-run and answer 'n' explicitly to abort cleanly"],"exampleFix":"# before\npicoclaw mcp add fs npx -y @mcp/fs | tee add.log\n# after\npicoclaw mcp add --force fs npx -y @mcp/fs | tee add.log","handlingStrategy":"validation","validationCode":"# non-interactive context: always pass --force, never rely on the prompt\nif [ ! -t 0 ] || [ ! -t 1 ]; then FORCE=--force; else FORCE=\"\"; fi\npicoclaw mcp add $FORCE \"$@\"","typeGuard":null,"tryCatchPattern":"ok, err := confirmOverwrite(in, out, name)\nif err != nil {\n    if errors.Is(err, io.EOF) {\n        return false // treat closed stdin as a clean no\n    }\n    return fmt.Errorf(\"failed to confirm overwrite: %w\", err)\n}","preventionTips":["Use --force in scripts/CI to bypass the prompt","Do not pipe mcp add stdout into early-exiting readers","Answer prompts with explicit y/n; avoid bare Enter (it errors as 'unexpected newline')"],"tags":["mcp","cli","interactive","io"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}