summaryrefslogtreecommitdiff
path: root/internal/askcli
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-29 17:39:29 +0300
committerPaul Buetow <paul@buetow.org>2026-05-29 17:39:29 +0300
commit5b49734f3e2bba38e689f274d39e5ff3b52f529d (patch)
treef34085421da47a11761412e315fa78ac94cfb154 /internal/askcli
parentb3cf20116d403e4437a2aaa726bdcf188109cf9f (diff)
askcli: keep ask add successful when alias assignment fails
Diffstat (limited to 'internal/askcli')
-rw-r--r--internal/askcli/command_add.go13
-rw-r--r--internal/askcli/command_info_add_test.go21
2 files changed, 24 insertions, 10 deletions
diff --git a/internal/askcli/command_add.go b/internal/askcli/command_add.go
index b94fe89..096046d 100644
--- a/internal/askcli/command_add.go
+++ b/internal/askcli/command_add.go
@@ -45,10 +45,15 @@ func (d *Dispatcher) handleAdd(ctx context.Context, args []string, stdout, stder
_, _ = io.WriteString(stderr, "error: could not parse UUID from task creation output\n")
return 1, nil
}
- aliases, err := ensureTaskAliasesForUUIDs([]string{uuid})
- if err != nil {
- fmt.Fprintf(stderr, "error: failed to assign task alias: %v\n", err)
- return 1, nil
+ // The task is already created in Taskwarrior. If alias assignment fails
+ // (e.g. cache lock timeout, validation error, disk full), surface the
+ // problem as a warning on stderr but still report success on stdout with
+ // exit 0 so the user does not retry and create a duplicate task. The
+ // displayed identifier falls back to the UUID when no alias is available.
+ aliases, aliasErr := ensureTaskAliasesForUUIDs([]string{uuid})
+ if aliasErr != nil {
+ fmt.Fprintf(stderr, "warning: failed to assign task alias: %v\n", aliasErr)
+ aliases = nil
}
_, _ = io.WriteString(stdout, FormatCreatedTask(displayTaskAlias(uuid, aliases)))
return 0, nil
diff --git a/internal/askcli/command_info_add_test.go b/internal/askcli/command_info_add_test.go
index b6f0bd0..b918518 100644
--- a/internal/askcli/command_info_add_test.go
+++ b/internal/askcli/command_info_add_test.go
@@ -342,6 +342,12 @@ func TestHandleAdd_Success(t *testing.T) {
}
}
+// TestHandleAdd_AliasAssignmentFailure verifies that when alias assignment
+// fails after the task is already created in Taskwarrior, the command still
+// exits 0 and prints "created task <uuid>" on stdout (with the UUID as
+// fallback identifier), while emitting the failure as a warning on stderr.
+// This prevents the previous bug where the user saw exit 1 and retried,
+// creating duplicate tasks.
func TestHandleAdd_AliasAssignmentFailure(t *testing.T) {
oldRoot := taskAliasCacheRoot
taskAliasCacheRoot = func() (string, error) { return "", io.ErrUnexpectedEOF }
@@ -354,14 +360,17 @@ func TestHandleAdd_AliasAssignmentFailure(t *testing.T) {
var stdout, stderr bytes.Buffer
code, _ := d.Dispatch(context.Background(), []string{"add", "New task description"}, nil, &stdout, &stderr)
- if code != 1 {
- t.Fatalf("add code = %d, want 1", code)
+ if code != 0 {
+ t.Fatalf("add code = %d, want 0 (task was created, alias failure is non-fatal)", code)
+ }
+ if got := strings.TrimSpace(stdout.String()); got != "created task abc-123-def" {
+ t.Fatalf("stdout = %q, want \"created task abc-123-def\" (UUID fallback)", stdout.String())
}
- if stdout.Len() != 0 {
- t.Fatalf("stdout = %q, want empty output on alias assignment failure", stdout.String())
+ if !strings.Contains(stderr.String(), "warning: failed to assign task alias") {
+ t.Fatalf("stderr = %q, want warning about alias assignment failure", stderr.String())
}
- if !strings.Contains(stderr.String(), "failed to assign task alias") {
- t.Fatalf("stderr = %q, want alias assignment failure", stderr.String())
+ if strings.Contains(stderr.String(), "error: failed to assign task alias") {
+ t.Fatalf("stderr = %q, alias failure should be a warning, not an error", stderr.String())
}
}