apache/pulsar · critical

When Guarantees == %s, autoAck must be equal to true. If you

Error message

When Guarantees == %s, autoAck must be equal to true. If you want not to automatically ack, please configure the processing guarantees as MANUAL. This is a contradictory configuration, autoAck will be removed later. Please refer to PIP: https://github.com/apache/pulsar/issues/15560

What it means

For ATLEAST_ONCE/ATMOST_ONCE guarantees the runtime relies on automatic acknowledgement; a config that disables AutoAck while requesting these guarantees is contradictory. newInstanceConfWithConf panics with this explanatory message pointing to PIP 15560 (autoAck deprecation), telling the user to use MANUAL instead.

Source

Thrown at pulsar-function-go/pf/instanceConf.go:144

	}
	// parse the raw function details and ignore the unmarshal error(fallback to original way)
	if cfg.FunctionDetails != "" {
		functionDetails := pb.FunctionDetails{}
		if err := protojson.Unmarshal([]byte(cfg.FunctionDetails), &functionDetails); err != nil {
			log.Errorf("Failed to unmarshal function details: %v", err)
		} else {
			instanceConf.funcDetails = functionDetails
		}
	}

	if instanceConf.funcDetails.ProcessingGuarantees == pb.ProcessingGuarantees_EFFECTIVELY_ONCE {
		panic("Go instance current not support EFFECTIVELY_ONCE processing guarantees.")
	}

	if !instanceConf.funcDetails.AutoAck && //nolint:staticcheck
		(instanceConf.funcDetails.ProcessingGuarantees == pb.ProcessingGuarantees_ATMOST_ONCE ||
			instanceConf.funcDetails.ProcessingGuarantees == pb.ProcessingGuarantees_ATLEAST_ONCE) {
		panic("When Guarantees == " + instanceConf.funcDetails.ProcessingGuarantees.String() +
			", autoAck must be equal to true. If you want not to automatically ack, " +
			"please configure the processing guarantees as MANUAL." +
			" This is a contradictory configuration, autoAck will be removed later." +
			" Please refer to PIP: https://github.com/apache/pulsar/issues/15560")
	}

	return instanceConf
}

func newInstanceConf() *instanceConf {
	config := &conf.Conf{}
	cfg := config.GetConf()
	if cfg == nil {
		panic("config file is nil.")
	}
	return newInstanceConfWithConf(cfg)
}

View on GitHub (pinned to 820761864e)

Solutions

  1. Set AutoAck=true when using ATMOST_ONCE or ATLEAST_ONCE.
  2. If manual acking is desired, set ProcessingGuarantees to MANUAL instead of disabling autoAck.
  3. Update configs/templates to stop relying on autoAck=false (deprecated per PIP 15560).

Example fix

// before
autoAck: false
processingGuarantees: ATLEAST_ONCE // contradictory
// after
processingGuarantees: MANUAL // for manual acks
// or
autoAck: true
processingGuarantees: ATLEAST_ONCE
Defensive patterns

Strategy: validation

Validate before calling

if !details.AutoAck && (details.ProcessingGuarantees == pb.ProcessingGuarantees_ATMOST_ONCE ||
    details.ProcessingGuarantees == pb.ProcessingGuarantees_ATLEAST_ONCE) {
    return fmt.Errorf("contradictory config: set MANUAL for manual acks, or enable autoAck")
}

Try / catch

defer func() {
    if r := recover(); r != nil {
        if s, ok := r.(string); ok && strings.Contains(s, "autoAck must be equal to true") {
            log.Fatalf("fix guarantees/autoAck combination: %s", s)
        }
        panic(r)
    }
}()

Prevention

When it happens

Trigger: FunctionDetails with AutoAck=false and ProcessingGuarantees = ATMOST_ONCE or ATLEAST_ONCE.

Common situations: Users trying to manually ack with the Go runtime while keeping at-least-once; configs migrated from deprecated autoAck toggling; confusion between autoAck and MANUAL guarantees after the PIP.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/372d9fad794b5667. Report an issue: GitHub.