vxcontrol/pentagi · warning

input must not be empty

Error message

input must not be empty

What it means

submit_flow_input parsed successfully but action.Input was an empty string, so the tool rejects the call before touching the database. Submitting empty input is meaningless — the tool exists to feed new instructions/data into a running flow — and this is an explicit domain validation rather than a JSON error.

Source

Thrown at backend/pkg/tools/flow_manager.go:703

func NewSubmitFlowInputTool(flowID int64, db database.Querier, handler func(ctx context.Context, input string) error) *submitFlowInputTool {
	return &submitFlowInputTool{
		flowID:       flowID,
		db:           db,
		handler:      handler,
		pollInterval: taskReadyPollInterval,
		pollTimeout:  taskReadyPollTimeout,
	}
}

func (t *submitFlowInputTool) Handle(ctx context.Context, name string, args json.RawMessage) (string, error) {
	var action SubmitFlowInputAction
	if err := json.Unmarshal(args, &action); err != nil {
		return "", fmt.Errorf("failed to parse %s args: %w", SubmitFlowInputToolName, err)
	}

	if action.Input == "" {
		return "", fmt.Errorf("input must not be empty")
	}

	tasks, err := t.db.GetFlowTasks(ctx, t.flowID)
	if err != nil {
		return "", fmt.Errorf("failed to check flow status: %w", err)
	}

	for _, task := range tasks {
		if task.Status == database.TaskStatusRunning {
			return fmt.Sprintf(
				"Cannot submit input: task %q (ID: %d) is currently running. "+
					"Call %s first to stop the current execution, then retry %s. "+
					"Use %s to confirm the flow reaches 'waiting' state before retrying",
				task.Title, task.ID, StopFlowToolName, SubmitFlowInputToolName, GetFlowStatusToolName,
			), nil
		}
	}

View on GitHub (pinned to ea665308ba)

Solutions

  1. Provide a non-empty input string: {"input": "<actual instruction or data>"}.
  2. Trim/validate the input at the call site before invoking the tool.
  3. Fix upstream interpolation — check the variable feeding input is populated.
  4. If input is optional, use a different flow-control tool instead of submitting empty input.

Example fix

// before
await submitFlowInput(flowId, '');
// after
const input = userText.trim();
if (input) await submitFlowInput(flowId, input);
Defensive patterns

Strategy: validation

Validate before calling

function validateSubmitInput(input: string): string {
  const trimmed = input.trim();
  if (!trimmed) throw new Error('input must not be empty');
  return trimmed;
}
// call only after validation passes

Type guard

function hasNonEmptyInput(v: unknown): v is { input: string } {
  return typeof v === 'object' && v !== null &&
    typeof (v as any).input === 'string' && (v as any).input.length > 0;
}

Try / catch

try {
  await tool.call('submit_flow_input', { input });
} catch (err) {
  if (String(err).includes('input must not be empty')) {
    // prompt user / regenerate a non-empty instruction
  }
}

Prevention

When it happens

Trigger: Calling submit_flow_input with {"input": ""}, {"input": " "} is allowed only if not trimmed (empty string exactly), or with the input field omitted after a successful unmarshal into the zero-value struct (e.g. args = {}).

Common situations: LLM generates an empty input placeholder; a caller builds args dynamically from a variable that was empty; a UI form allowed submission without filling the field; variable interpolation produced an empty string.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01). Data as JSON: /api/errors/d1ea7aff50137c6c. Report an issue: GitHub.