pulumi/pulumi · error

callback not found:

Error message

callback not found: 

What it means

The PCL interpreter hosts a local callback gRPC server (pclCallbackServer); callbacks are registered under a UUID token and the engine invokes them by token. If an Invoke request carries a token that has no registered function, the server returns "callback not found: <token>". This means the callback was never registered, or it was invoked after the interpreter/session ended.

Source

Thrown at pkg/pcl/runtime/interpreter.go:162

	defer s.functionsLock.Unlock()
	s.functions[uuidString] = fn
	return &pulumirpc.Callback{
		Token:  uuidString,
		Target: "127.0.0.1:" + strconv.Itoa(s.handle.Port),
		// PCL decodes strings containing non-UTF8 bytes losslessly, so the engine may send them to callbacks
		// hosted here.
		AcceptsByteString: true,
	}, nil
}

func (s *pclCallbackServer) Invoke(
	ctx context.Context, req *pulumirpc.CallbackInvokeRequest,
) (*pulumirpc.CallbackInvokeResponse, error) {
	s.functionsLock.RLock()
	fn, ok := s.functions[req.Token]
	s.functionsLock.RUnlock()
	if !ok {
		return nil, errors.New("callback not found: " + req.Token)
	}
	resp, err := fn(ctx, req.Request)
	if err != nil {
		return nil, err
	}
	b, err := proto.Marshal(resp)
	if err != nil {
		return nil, fmt.Errorf("marshaling callback response: %w", err)
	}
	return &pulumirpc.CallbackInvokeResponse{Response: b}, nil
}

func (i *Interpreter) getCallbackServer() (*pclCallbackServer, error) {
	i.callbacksOnce.Do(func() {
		s, err := newPCLCallbackServer()
		i.callbacks = s
		i.callbacksErr = err
	})

View on GitHub (pinned to 793f7b2e16)

Solutions

  1. Re-run the program so hooks re-register fresh callback tokens; discard stale tokens from prior runs
  2. Verify the callback Token/Target pair matches the interpreter instance currently serving
  3. Avoid persisting or replaying callback tokens across deployments/runs
  4. If concurrent, ensure each interpreter has its own callback server port and tokens are not mixed
Defensive patterns

Strategy: retry

Try / catch

_, err := callbackClient.Invoke(ctx, req)
if err != nil && strings.HasPrefix(err.Error(), "callback not found") {
    // re-run the program to obtain fresh tokens; do not blindly retry with same token
}

Prevention

When it happens

Trigger: pclCallbackServer.Invoke (pkg/pcl/runtime/interpreter.go:162) looks up req.Token in s.functions and misses — e.g. the engine invokes a stale/expired callback token, or invokes a callback belonging to a different interpreter instance.

Common situations: Hook callbacks invoked after the program finished, retry of a failed operation reusing an old callback token, running multiple concurrent interpreters where tokens are sent to the wrong port, or cached state from a previous run being replayed.

Related errors


AI-assisted analysis of pulumi/pulumi@793f7b2e16 (2026-08-31). Data as JSON: /api/errors/e2126f151a4edda0. Report an issue: GitHub.