apache/beam · error
error getting last message
Error message
error getting last message: %v
What it means
After fetching the stream, getEndSeqNo calls str.GetLastMsgForSubject(ctx, e.subject) to find the last message for the configured subject. If that request fails for a reason other than 'message not found' (which is handled by returning 1), the error is wrapped with this message and Estimate fails. It indicates the last-message lookup could not be completed against the JetStream stream.
Solutions
- Read the wrapped error to distinguish timeouts/cancellation from server errors
- Validate the subject matches the stream's subjects (`nats stream info <name>` shows subjects)
- Increase the context timeout passed to Estimate/getEndSeqNo if deadlines fire
- Retry the operation on transient network errors; confirm the connection is healthy
- Check NATS server logs for JetStream errors at the time of the request
Example fix
// before ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) // after ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) // generous deadline for large streams
Defensive patterns
Strategy: retry
Validate before calling
// pre-flight: ensure the subject is served by the stream
str, _ := js.Stream(ctx, streamName)
for _, subj := range str.CachedInfo().Config.Subjects {
if subjectsMatch(subj, configuredSubject) { return nil }
}
return errors.New("subject not covered by stream; check configuration") Try / catch
msg, err := str.GetLastMsgForSubject(ctx, e.subject)
if err != nil {
if isMessageNotFound(err) { return 1, nil }
if errors.Is(err, context.DeadlineExceeded) || isTransient(err) {
// retry with backoff before failing
}
return -1, fmt.Errorf("error getting last message: %v", err)
} Prevention
- Use context timeouts proportional to expected stream size
- Validate subject patterns against the stream's configured subjects
- Implement bounded retries for transient NATS errors
- Keep the NATS connection warm and monitor server health before estimation
- Log the wrapped cause to distinguish subject errors from network failures
When it happens
Trigger: str.GetLastMsgForSubject returns a non-nil error that isMessageNotFound(err) does not classify as not-found: invalid subject in the request, context cancellation/timeout, server-side JetStream errors, or connection loss mid-request.
Common situations: Subject configured with a token mismatch or malformed wildcard so the server rejects the request; slow NATS server causing the context deadline to fire; transient network failure between worker and server; server returning an internal JetStream error.
Understand the failure class
Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.
Related errors
- error creating JetStream context
- error getting stream
- err
- error connecting to NATS
- error creating consumer
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/dd9f751d168c3d1a.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/go/pkg/beam/io/natsio/end_estimator.go:61
if err != nil {
panic(err)
}
return end
}
func (e *endEstimator) getEndSeqNo(ctx context.Context) (int64, error) {
str, err := e.js.Stream(ctx, e.stream)
if err != nil {
return -1, fmt.Errorf("error getting stream: %v", err)
}
msg, err := str.GetLastMsgForSubject(ctx, e.subject)
if err != nil {
if isMessageNotFound(err) {
return 1, nil
}
return -1, fmt.Errorf("error getting last message: %v", err)
}
return int64(msg.Sequence) + 1, nil
}
func isMessageNotFound(err error) bool {
var jsErr jetstream.JetStreamError
if errors.As(err, &jsErr) {
apiErr := jsErr.APIError()
if apiErr.ErrorCode == jetstream.JSErrCodeMessageNotFound {
return true
}
}
return false
}
View on GitHub (pinned to 12126d8942)