fix(utils): prevent nil pointer panic in ResolvePartialID (#1132)
Add nil check at start of ResolvePartialID to return a proper error instead of panicking when storage interface is nil. Root cause: When bd refile (or other commands) is called with a nil storage, calling store.SearchIssues() panics with SIGSEGV. This can happen when routing fails to initialize storage properly. Now returns: "cannot resolve issue ID <id>: storage is nil" Fixes: bd-7ypor Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -37,6 +37,10 @@ func ParseIssueID(input string, prefix string) string {
|
|||||||
// - No issue found matching the ID
|
// - No issue found matching the ID
|
||||||
// - Multiple issues match (ambiguous prefix)
|
// - Multiple issues match (ambiguous prefix)
|
||||||
func ResolvePartialID(ctx context.Context, store storage.Storage, input string) (string, error) {
|
func ResolvePartialID(ctx context.Context, store storage.Storage, input string) (string, error) {
|
||||||
|
if store == nil {
|
||||||
|
return "", fmt.Errorf("cannot resolve issue ID %q: storage is nil", input)
|
||||||
|
}
|
||||||
|
|
||||||
// Fast path: Use SearchIssues with exact ID filter (GH#942).
|
// Fast path: Use SearchIssues with exact ID filter (GH#942).
|
||||||
// This uses the same query path as "bd list --id", ensuring consistency.
|
// This uses the same query path as "bd list --id", ensuring consistency.
|
||||||
// Previously we used GetIssue which could fail in cases where SearchIssues
|
// Previously we used GetIssue which could fail in cases where SearchIssues
|
||||||
|
|||||||
@@ -316,6 +316,21 @@ func TestResolvePartialID_NoConfig(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestResolvePartialID_NilStorage(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
// Test that nil storage returns an error instead of panicking
|
||||||
|
_, err := ResolvePartialID(ctx, nil, "bd-123")
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("ResolvePartialID with nil storage should return error, got nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedMsg := "storage is nil"
|
||||||
|
if !contains(err.Error(), expectedMsg) {
|
||||||
|
t.Errorf("ResolvePartialID error = %q; want error containing %q", err.Error(), expectedMsg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestExtractIssuePrefix(t *testing.T) {
|
func TestExtractIssuePrefix(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
|||||||
Reference in New Issue
Block a user