micro/go-micro · error

remote task %s ended in state %q

Error message

remote task %s ended in state %q

What it means

Send submits an A2A message and polls the resulting remote task until it reaches a terminal state. The library throws this error when the task finished in a terminal state other than completed (e.g. failed, canceled, rejected), meaning no result text can be returned. The message includes the remote task ID and the actual state string so callers can correlate and diagnose.

Source

Thrown at gateway/a2a/client.go:75

	}
	return &card, nil
}

// Send sends a text message to the remote agent and returns its reply.
// If the agent returns a task that isn't yet terminal, Send polls
// tasks/get until it completes or ctx is done.
func (c *Client) Send(ctx context.Context, text string) (string, error) {
	task, err := c.SendMessage(ctx, Message{
		Role:      "user",
		Kind:      "message",
		MessageID: uuid.New().String(),
		Parts:     []Part{{Kind: "text", Text: text}},
	})
	if err != nil {
		return "", err
	}
	if task.Status.State != stateCompleted {
		return "", fmt.Errorf("remote task %s ended in state %q", task.ID, task.Status.State)
	}
	return artifactsText(task.Artifacts), nil
}

// SendMessage sends an A2A message and returns the resulting terminal task.
// To continue a multi-turn task, pass a Message with TaskID and ContextID set
// to a prior task's id and context id.
func (c *Client) SendMessage(ctx context.Context, message Message) (*Task, error) {
	if message.MessageID == "" {
		message.MessageID = uuid.New().String()
	}
	if message.Kind == "" {
		message.Kind = "message"
	}
	if message.Role == "" {
		message.Role = "user"
	}
	res, err := c.call(ctx, "message/send", sendParams{Message: message})

View on GitHub (pinned to 24529f1404)

Solutions

  1. Read the state value in the error; if 'failed', fetch task details or logs from the remote agent for the underlying cause.
  2. Inspect the task status message/artifacts via the task ID to get agent-reported error details.
  3. Retry the send if the failure was transient (upstream model/tool outage); implement idempotency keys if the agent supports them.
  4. Handle 'canceled' explicitly in caller flow (surface to user rather than retrying).
Defensive patterns

Strategy: try-catch

Try / catch

text, err := c.Send(ctx, msg)
if err != nil {
	var stateErr *taskStateError // or regex the state from the message
	if m := stateRe.FindStringSubmatch(err.Error()); m != nil {
		switch m[2] {
		case "canceled": return errCanceled
		case "failed": return retryableOrNot(err)
		}
	}
	return err
}

Prevention

When it happens

Trigger: Calling SendMessage when the remote agent marks the task 'failed' due to a processing error, 'canceled' by the user or a timeout, or any custom terminal state the agent reports other than the library's stateCompleted value.

Common situations: The remote agent rejected the input (invalid parameters, unsupported capability); the task was canceled after a deadline; the agent-side model or tool call crashed mid-task; an operator canceled long-running work.

Related errors


AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01). Data as JSON: /api/errors/f65dac7201285542. Report an issue: GitHub.