ruvnet/ruflo · error

must be non-empty

Error message

${label} must be non-empty

What it means

createBuildEvidence trims every declared string — build input name, build input path (via normalizePath), toolchain name, and toolchain version — and throws when the trimmed result is empty. The label in the message identifies the exact field that failed (e.g. 'build input name must be non-empty').

Solutions

  1. Check the label in the message to identify which declaration field is blank
  2. Populate the field or remove the empty declaration entirely — empty arrays are accepted, blank entries are not
  3. When generating declarations programmatically, trim and assert non-empty at the source that builds them

Example fix

// before
const buildInputs = [
  { name: '   ', path: 'dist/app.js', digest: d, bytes: 1024 }, // blank name
];

// after
const buildInputs = [
  { name: 'app-bundle', path: 'dist/app.js', digest: d, bytes: 1024 },
];
Defensive patterns

Strategy: validation

Validate before calling

function validateDeclarations(inputs: { name: string }[], tools: { name: string; version: string }[]): void {
  for (const i of inputs) if (!i.name.trim()) throw new Error('build input name is blank');
  for (const t of tools) {
    if (!t.name.trim()) throw new Error('toolchain name is blank');
    if (!t.version.trim()) throw new Error('toolchain version is blank');
  }
}

Try / catch

Catch around createBuildEvidence/captureBuildEvidence and map the '<label> must be non-empty' message back to the offending declaration index so users see which entry (not just which field) is blank.

Prevention

When it happens

Trigger: A DeclaredBuildInput or ToolchainDeclaration whose name or version is '', ' ', or whitespace-only; a build input path that is blank (fails before the unsafe-path checks run).

Common situations: Optional string fields left as '' instead of omitted; declaration objects built from missing keys; placeholders like 'TODO' removed by a trim before the call; config generators emitting blank rows for skipped entries.

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 ruvnet/ruflo@fa13ee4ad6 (2026-08-18). Data as JSON: /api/errors/ce4a57e83dd36f9e. Report an issue: GitHub.

Appendix: source

Thrown at v3/@claude-flow/codex/src/harness/build-evidence.ts:55

  path: string;
}

export interface BuildEvidence {
  contractVersion: 1;
  assurance: 'declared-unsigned';
  sourceStateId: string;
  buildInputs: readonly DeclaredBuildInput[];
  toolchains: readonly DeclaredToolchain[];
  evidenceDigest: string;
}

function compare(left: string, right: string): number {
  return left < right ? -1 : left > right ? 1 : 0;
}

function requireText(value: string, label: string): string {
  const result = value.trim();
  if (!result) throw new Error(`${label} must be non-empty`);
  return result;
}

function requireDigest(value: string, label: string): string {
  if (!DIGEST.test(value)) throw new Error(`${label} must be a canonical sha256 digest`);
  return value;
}

function normalizePath(value: string): string {
  const path = requireText(value, 'build input path');
  if (
    path.includes('\\')
    || path.startsWith('/')
    || path.startsWith('-')
    || path !== path.normalize('NFC')
    || path.split('/').some((part) => !part || part === '.' || part === '..')
  ) {
    throw new Error(`unsafe build input path: ${value}`);

View on GitHub (pinned to fa13ee4ad6)