{"record":{"id":"07e70638499b34be","repo":"gastownhall/beads","slug":"peer-remote-q-has-credentials-and-requires-cli-ro","errorCode":null,"errorMessage":"peer remote %q has credentials and requires CLI routing: %w","messagePattern":"peer remote %q has credentials and requires CLI routing: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/dolt/credentials.go","lineNumber":648,"sourceCode":"\nfunc (s *DoltStore) prepareCLIRouteForPeerCredentials(ctx context.Context, peer string, creds *remoteCredentials) (bool, error) {\n\tif creds.empty() {\n\t\treturn false, nil // no credentials to pass\n\t}\n\tif !s.serverMode {\n\t\treturn false, nil // embedded mode: withEnvCredentials works in-process\n\t}\n\tif !s.hasCLIDatabase() {\n\t\treturn false, nil\n\t}\n\tremotes, err := s.ListRemotes(ctx)\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"list Dolt remotes before credential routing for peer %q: %w\", peer, err)\n\t}\n\tfor _, r := range remotes {\n\t\tif r.Name == peer {\n\t\t\tif err := s.ensureMatchingCLIRemote(peer, r.URL); err != nil {\n\t\t\t\treturn false, fmt.Errorf(\"peer remote %q has credentials and requires CLI routing: %w\", peer, err)\n\t\t\t}\n\t\t\treturn true, nil\n\t\t}\n\t}\n\treturn false, nil\n}\n\nfunc (s *DoltStore) shouldUseCLIForPeerCredentialsWithError(ctx context.Context, peer string, creds *remoteCredentials) (bool, error) {\n\treturn s.prepareCLIRouteForPeerCredentials(ctx, peer, creds)\n}\n\n// shouldUseCLIForCredentials returns true when CLI subprocess routing should\n// be used instead of SQL path for credential-bearing push/pull operations.\n//\n// When true, callers should route through doltCLIPush/Pull instead of\n// CALL DOLT_PUSH/PULL, because withEnvCredentials() sets env vars on the\n// bd client process — the external server process cannot see them.\n//","sourceCodeStart":630,"sourceCodeEnd":666,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dolt/credentials.go#L630-L666","documentation":"When a peer has stored credentials and a matching Dolt remote exists, bd must materialize that remote into the local CLI directory before routing the operation through the CLI subprocess. This error wraps ensureMatchingCLIRemote failing during that setup — the CLI route was required but could not be prepared. The library throws it rather than silently falling back to the SQL path, which would fail authentication with an external server.","triggerScenarios":"ensureMatchingCLIRemote fails to create/update the peer remote in the CLI database directory: the local .beads/dolt CLI dir is missing/corrupt, the dolt CLI binary is unavailable or fails, file permissions block the CLI directory, or the remote URL can't be materialized.","commonSituations":"Server mode (external dolt-sql-server) with peer credentials where the local CLI database directory wasn't initialized; dolt binary not on PATH; mismatched remote URL between SQL and CLI dirs; permissions on .beads/dolt after running as different users.","solutions":["Ensure the dolt CLI binary is installed and on PATH (dolt version).","Verify the local CLI database directory (.beads/dolt) exists and is writable; re-initialize if corrupt.","Confirm the remote URL matches between the SQL server and CLI dir; remove and re-add the peer so both sides re-sync.","If CLI routing is unnecessary for your setup, clear the peer's stored credentials or run in embedded mode where the SQL path handles env credentials in-process."],"exampleFix":"// before: dolt missing on PATH in server mode\nok, err := shouldUseCLIForPeerCredentialsWithError(ctx, \"peer\", creds) // requires CLI routing: exec: \"dolt\": executable file not found\n// after: install dolt CLI and ensure CLI db is initialized\nbrew install dolt || sudo apt-get install dolt\nok, err = shouldUseCLIForPeerCredentialsWithError(ctx, \"peer\", creds)","handlingStrategy":"validation","validationCode":"// before credential routing, verify CLI prerequisites\nif _, err := exec.LookPath(\"dolt\"); err != nil {\n    return fmt.Errorf(\"dolt CLI required for credential routing in server mode: %w\", err)\n}\nif info, err := os.Stat(cliDoltDir); err != nil || !info.IsDir() {\n    return fmt.Errorf(\"CLI database dir %s missing\", cliDoltDir)\n}","typeGuard":null,"tryCatchPattern":"ok, err := shouldUseCLIForPeerCredentialsWithError(ctx, peer, creds)\nif err != nil && strings.Contains(err.Error(), \"requires CLI routing\") {\n    // fix dolt CLI/CLI dir, or fall back: clear peer creds to avoid CLI routing\n    log.Printf(\"CLI route unavailable: %v\", err)\n}","preventionTips":["Install the dolt CLI on hosts running server-mode bd","Keep the local CLI database directory initialized and writable","Keep remote URLs identical between SQL server and CLI dir","Run all bd processes as the same user to avoid permission drift"],"tags":["cli","remotes","credentials","server-mode","routing"],"backgroundTag":"cli-remote-setup-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}