wavetermdev/waveterm · error

must provide a builderId to StartBuilderCommand

Error message

must provide a builderId to StartBuilderCommand

What it means

StartBuilderCommand starts a builder's build process via buildercontroller.GetOrCreateController, but first requires data.BuilderId to be non-empty. An empty id would create/lookup a controller keyed by "", so the server fails fast with this error.

Source

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

func (ws *WshServer) WriteAppSecretBindingsCommand(ctx context.Context, data wshrpc.CommandWriteAppSecretBindingsData) error {
	if data.AppId == "" {
		return fmt.Errorf("must provide an appId to WriteAppSecretBindingsCommand")
	}
	return waveappstore.WriteAppSecretBindings(data.AppId, data.Bindings)
}

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

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)

View on GitHub (pinned to a4447c1563)

Solutions

  1. Set BuilderId from the selected builder's OID before calling
  2. Wait for builder state to load in the client before enabling the start action
  3. Validate data non-empty on the client side before the RPC

Example fix

// before
client.StartBuilderCommand(ctx, wshrpc.CommandStartBuilderData{})
// after
client.StartBuilderCommand(ctx, wshrpc.CommandStartBuilderData{BuilderId: builder.OID})
Defensive patterns

Strategy: validation

Validate before calling

if data.BuilderId == "" {
    return fmt.Errorf("cannot start builder: BuilderId is empty")
}
err := client.StartBuilderCommand(ctx, data)

Type guard

func startable(data wshrpc.CommandStartBuilderData) bool {
    return data.BuilderId != ""
}

Try / catch

if err := client.StartBuilderCommand(ctx, data); err != nil {
    if strings.Contains(err.Error(), "must provide a builderId") {
        // set BuilderId from selection and retry once
    }
    return err
}

Prevention

When it happens

Trigger: Invoking the StartBuilderCommand RPC with CommandStartBuilderData.BuilderId == "" — the client never set BuilderId, or resolved it from an empty UI/RTInfo field.

Common situations: Clicking 'start build' before a builder is selected; scripting the RPC with a partial data struct; state sync lag where the frontend's builder object is still empty.

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/d0439e08f73c6bb1. Report an issue: GitHub.