larksuite/cli · error

objective %s: %w

Error message

objective %s: %w

What it means

During rollback after a failed OKR batch create, each per-objective deletion failure is wrapped as `objective %s: %w`, preserving the delete error and the objective ID. These wraps are collected into an errors list and later assembled into a typed rollback error by buildRollbackError, so the user knows which objectives could not be cleaned up.

Source

Thrown at shortcuts/okr/okr_batch_create.go:170

	if err != nil {
		return wrapOkrNetworkErr(err, "failed to delete objective %s during rollback", objectiveID)
	}
	return nil
}

// rollback deletes created objectives in reverse order.
// KRs are automatically deleted by the backend when the objective is deleted.
func rollback(ctx context.Context, runtime *common.RuntimeContext, created []createdObjective) []error {
	var errsList []error

	// Iterate in reverse order
	for i := len(created) - 1; i >= 0; i-- {
		obj := created[i]

		// Delete the objective (backend automatically deletes its KRs)
		if err := deleteObjective(ctx, runtime, obj.ObjectiveID); err != nil {
			//nolint:forbidigo // intermediate wrap for rollback error collection; final error is typed via buildRollbackError
			errsList = append(errsList, fmt.Errorf("objective %s: %w", obj.ObjectiveID, err))
		}

		// Rate limiting between deletions
		if i > 0 {
			time.Sleep(500 * time.Millisecond)
		}
	}

	return errsList
}

// OKRBatchCreate batch creates objectives and their key results.
var OKRBatchCreate = common.Shortcut{
	Service:     "okr",
	Command:     "+batch-create",
	Description: "Batch create OKR objectives and key results with rollback on failure",
	Risk:        "write",
	Scopes:      []string{"okr:okr.content:writeonly"},

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Read the wrapped cause for the listed objective ID and fix the underlying delete failure (permissions, scopes, rate limits).
  2. Manually delete the leftover objective IDs reported by the rollback error via the OKR delete command.
  3. Retry the operation after resolving the cause; rollback errors indicate leftover state, not a problem with your input.
Defensive patterns

Strategy: try-catch

Try / catch

err := batchCreate(ctx, runtime, objectives)
if err != nil {
    var rb *errs.TypedError
    if errors.As(err, &rb) && strings.Contains(err.Error(), "objective") {
        // parse leftover objective IDs from the wrapped message and delete them manually
        for _, id := range extractObjectiveIDs(err.Error()) {
            _ = deleteObjective(ctx, runtime, id)
        }
    }
}

Prevention

When it happens

Trigger: A batch OKR create partially succeeded, rollback began, and deleteObjective failed for a specific objective ID — e.g. the objective was already deleted, permissions were revoked, or a rate limit hit that specific call.

Common situations: Partial batch failures where some objectives were created before the batch aborted; concurrent edits removed the objective mid-rollback; transient API outages or permission-scoped tokens that can create but not delete.


AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04). Data as JSON: /api/errors/7bc3f36d5e72188e. Report an issue: GitHub.