dagger/dagger · error

startInteractivePromptMode: no ID found in LLM object: %+v

Error message

startInteractivePromptMode: no ID found in LLM object: %+v

What it means

startInteractivePromptMode(WithResume) extracts an LLM ID from the function response: if the response is a map[string]any it must contain a string 'id' key. This error means the map-shaped LLM response lacked an 'id' field, so the interactive prompt shell cannot load the LLM.

Source

Thrown at internal/cmd/dagger/functions.go:1096

	return startInteractivePromptModeWithResume(ctx, dag, response, "", false)
}

// startInteractivePromptModeWithResume is like startInteractivePromptMode but
// optionally resumes a previously saved session before entering the interactive
// loop. When resume is true and sessionID is empty, an interactive picker is
// shown; when sessionID is non-empty, that session is resumed directly. The
// resumed conversation replaces the composed LLM as the starting point.
func startInteractivePromptModeWithResume(ctx context.Context, dag *dagger.Client, response any, sessionID string, resume bool) error {
	// Extract the LLM ID from the response
	var llmID string
	switch v := response.(type) {
	case string:
		llmID = v
	case map[string]any:
		if id, ok := v["id"].(string); ok {
			llmID = id
		} else {
			return fmt.Errorf("startInteractivePromptMode: no ID found in LLM object: %+v", v)
		}
	default:
		return fmt.Errorf("startInteractivePromptMode: unexpected response type for LLM: %T", v)
	}

	// Set up the shell handler with prompt mode
	handler := newShellCallHandler(dag, Frontend)
	handler.mode = modePrompt

	// Initialize the handler
	if err := handler.Initialize(ctx); err != nil {
		return err
	}

	// Load the LLM from the ID and assign it as $agent
	llm := dagger.Ref[*dagger.LLM](dag, dagger.ID(llmID))
	if _, err := handler.llm(ctx); err != nil { // init llmSession
		return err

View on GitHub (pinned to 82ba2681db)

Solutions

  1. Make the function return an actual LLM object (or its ID string) so the response carries an 'id' field.
  2. If the response is a map, ensure it includes {"id": "<valid LLM ID>"}.
  3. Update the module to a version whose prompt-mode entry function returns dagger.LLM.

Example fix

// before (module returns plain object)
func (m *Mod) Assistant() map[string]any { return map[string]any{"model": "gpt"} }
// after
func (m *Mod) Assistant() *dagger.LLM { return dag.LLM() }
Defensive patterns

Strategy: type-guard

Validate before calling

m, ok := response.(map[string]any)
if ok {
    if _, hasID := m["id"].(string); !hasID {
        return errors.New("response object missing id")
    }
}

Type guard

func hasLLMID(response any) bool {
    switch v := response.(type) {
    case string:
        return v != ""
    case map[string]any:
        _, ok := v["id"].(string)
        return ok
    default:
        return false
    }
}

Try / catch

if err := startInteractivePromptMode(ctx, dag, resp); err != nil {
    if strings.Contains(err.Error(), "no ID found in LLM object") {
        // inspect resp and fix module return type
    }
}

Prevention

When it happens

Trigger: A module function returning an object serialized to a map without an 'id' key (e.g. a custom struct or partial object instead of a dagger LLM), then passed to `dagger call ... --interactive` / prompt mode.

Common situations: Module authors returning a plain object from the function intended for prompt mode; GraphQL/JSON deserialization producing a map missing 'id' after an API change; mixing object and ID return types across module versions.

Related errors


AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05). Data as JSON: /api/errors/8b332b9f91190620. Report an issue: GitHub.