hashicorp/nomad · error

driver does not support exec

Error message

driver does not support exec

What it means

The driver plugin implementation behind the server only satisfies the base driver interface; it implements neither ExecTaskStreamingRawDriver nor ExecTaskStreamingDriver, so exec streaming is not available. The server returns this error instead of attempting an unsupported capability.

Source

Thrown at plugins/drivers/server.go:334

func (b *driverPluginServer) ExecTaskStreaming(server proto.Driver_ExecTaskStreamingServer) error {
	msg, err := server.Recv()
	if err != nil {
		return fmt.Errorf("failed to receive initial message: %v", err)
	}

	if msg.Setup == nil {
		return fmt.Errorf("first message should always be setup")
	}

	if impl, ok := b.impl.(ExecTaskStreamingRawDriver); ok {
		return impl.ExecTaskStreamingRaw(server.Context(),
			msg.Setup.TaskId, msg.Setup.Command, msg.Setup.Tty,
			server)
	}

	d, ok := b.impl.(ExecTaskStreamingDriver)
	if !ok {
		return fmt.Errorf("driver does not support exec")
	}

	execOpts, errCh := StreamToExecOptions(server.Context(),
		msg.Setup.Command, msg.Setup.Tty,
		server)

	result, err := d.ExecTaskStreaming(server.Context(),
		msg.Setup.TaskId, execOpts)

	execOpts.Stdout.Close()
	execOpts.Stderr.Close()

	if err != nil {
		return err
	}

	// wait for copy to be done
	select {

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Use a driver that supports streaming exec, or implement ExecTaskStreamingDriver (or ExecTaskStreamingRawDriver) in the plugin.
  2. Upgrade the driver plugin binary to a version implementing the streaming exec interfaces.
  3. Change the task's driver configuration to one that supports exec, or avoid exec operations (e.g. exec/alloc fs commands) on this driver.

Example fix

// before
func (d *MyDriver) TaskConfigSchema() (*hclspec.Spec, error) { ... } // no exec methods
// after
func (d *MyDriver) ExecTaskStreamingRaw(ctx context.Context, taskID string, command []string, tty bool, stream proto.Driver_ExecTaskStreamingServer) error {
	return d.execRaw(ctx, taskID, command, tty, stream)
}
Defensive patterns

Strategy: type-guard

Validate before calling

// Before issuing exec, check driver capability
if _, ok := drv.(drivers.ExecTaskStreamingDriver); !ok {
	return errors.New("selected driver does not support streaming exec")
}

Type guard

func supportsExec(d interface{}) bool {
	_, raw := d.(drivers.ExecTaskStreamingRawDriver)
	_, std := d.(drivers.ExecTaskStreamingDriver)
	return raw || std
}

Try / catch

if err != nil && err.Error() == "driver does not support exec" {
	// fall back to a capable driver or surface a user-facing capability error
}

Prevention

When it happens

Trigger: Calling ExecTaskStreaming against a driver whose plugin implementation does not implement ExecTaskStreamingDriver (or the Raw variant), e.g. drivers without exec support.

Common situations: Using a driver that never implemented streaming exec (e.g. mock or restricted drivers); running an older plugin binary that predates the streaming exec interface while the host expects it; job/task driver configuration selecting a driver that lacks exec capability.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/60994fb230220ee9. Report an issue: GitHub.