wavetermdev/waveterm · error

must provide a builderId to StopBuilderCommand

Error message

must provide a builderId to StopBuilderCommand

What it means

StopBuilderCommand stops a running builder controller and requires a non-empty builderId. With an empty id the server cannot identify a controller, so it rejects the call before calling buildercontroller.GetController.

Source

Thrown at pkg/wshrpc/wshserver/wshserver.go:1155

func (ws *WshServer) StartBuilderCommand(ctx context.Context, data wshrpc.CommandStartBuilderData) error {
	if data.BuilderId == "" {
		return fmt.Errorf("must provide a builderId to StartBuilderCommand")
	}
	bc := buildercontroller.GetOrCreateController(data.BuilderId)
	rtInfo := wstore.GetRTInfo(waveobj.MakeORef("builder", data.BuilderId))
	if rtInfo == nil {
		return fmt.Errorf("builder rtinfo not found for builderid: %s", data.BuilderId)
	}
	appId := rtInfo.BuilderAppId
	if appId == "" {
		return fmt.Errorf("builder appid not set for builderid: %s", data.BuilderId)
	}
	return bc.Start(ctx, appId, rtInfo.BuilderEnv)
}

func (ws *WshServer) StopBuilderCommand(ctx context.Context, builderId string) error {
	if builderId == "" {
		return fmt.Errorf("must provide a builderId to StopBuilderCommand")
	}
	bc := buildercontroller.GetController(builderId)
	if bc == nil {
		return nil
	}
	return bc.Stop()
}

func (ws *WshServer) RestartBuilderAndWaitCommand(ctx context.Context, data wshrpc.CommandRestartBuilderAndWaitData) (*wshrpc.RestartBuilderAndWaitResult, error) {
	if data.BuilderId == "" {
		return nil, fmt.Errorf("must provide a builderId to RestartBuilderAndWaitCommand")
	}

	bc := buildercontroller.GetOrCreateController(data.BuilderId)
	rtInfo := wstore.GetRTInfo(waveobj.MakeORef("builder", data.BuilderId))
	if rtInfo == nil {
		return nil, fmt.Errorf("builder rtinfo not found for builderid: %s", data.BuilderId)
	}

View on GitHub (pinned to a4447c1563)

Solutions

  1. Pass the actual builder id to StopBuilderCommand
  2. Skip no-op stops client-side when the id is empty
  3. Verify the id source (UI selection, list entry) is populated

Example fix

// before
client.StopBuilderCommand(ctx, "")
// after
if builderId != "" {
    client.StopBuilderCommand(ctx, builderId)
}
Defensive patterns

Strategy: validation

Validate before calling

if builderId == "" {
    return nil // nothing to stop
}
err := client.StopBuilderCommand(ctx, builderId)

Type guard

func isNonEmpty(s string) bool { return s != "" }

Try / catch

if err := client.StopBuilderCommand(ctx, builderId); err != nil {
    if strings.Contains(err.Error(), "must provide a builderId") {
        return nil // treat as no-op
    }
    return err
}

Prevention

When it happens

Trigger: Calling StopBuilderCommand RPC with builderId == "" — unset variable in the caller, or an empty selection in the UI passed straight through.

Common situations: Stop-all handlers iterating a partially loaded builder list; teardown scripts with blank ids; copy-pasted RPC calls where the argument was dropped.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/45cb20b9d010bc30. Report an issue: GitHub.