windmill-labs/windmill · error · Error
Document must be a string
Error message
Document must be a string
What it means
The YAML validator's validate() method in windmill-yaml-validator/src/validation/yaml-validator.ts:113 requires the document to be a string, since it feeds it to parseWithPointers for source-mapped diagnostics. It throws "Document must be a string" when anything else (object, Buffer, undefined) is passed.
Source
Thrown at windmill-yaml-validator/src/validation/yaml-validator.ts:113
this.validateFlow = ajv.getSchema("#/components/schemas/OpenFlow")!;
this.validateSchedule = ajv.compile(scheduleSchema as AnySchema);
this.validateTrigger = Object.fromEntries(
SUPPORTED_TRIGGER_KINDS.map((kind) => [kind, ajv.compile(TRIGGER_SCHEMAS[kind])])
) as Record<TriggerKind, ValidateFunction>;
}
/**
* Validates a Windmill YAML document based on the selected target.
* @param doc - The YAML document as string
* @param target - Which Windmill schema to validate against
*/
validate(
doc: string,
target: ValidationTarget
): { parsed: YamlParserResult<unknown>; errors: ErrorObject[] } {
if (typeof doc !== "string") {
throw new Error("Document must be a string");
}
const parsed = parseWithPointers(doc);
const { data } = parsed;
let validator: ValidateFunction;
if (target.type === "flow") {
validator = this.validateFlow;
} else if (target.type === "schedule") {
validator = this.validateSchedule;
} else {
validator = this.validateTrigger[target.triggerKind];
if (!validator) {
throw new Error(`Unsupported trigger kind: ${target.triggerKind}`);
}
}
const ok = validator(data);View on GitHub (pinned to e474e8803c)
Solutions
- Pass the raw YAML text (fs.readFileSync(path, 'utf8'))
- If you have an object, YAML.stringify it first
- Log/typeof-check the doc argument to confirm it is a string
Example fix
// before
validator.validate(fs.readFileSync('flow.yaml'), { type: 'flow' })
// after
validator.validate(fs.readFileSync('flow.yaml', 'utf8'), { type: 'flow' }) Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof doc !== 'string') throw new TypeError('YAML document must be a raw string, got ' + typeof doc); Type guard
function isString(v: unknown): v is string { return typeof v === 'string'; } Try / catch
try {
validator.validate(doc, target);
} catch (e) {
if (e.message === 'Document must be a string') {
throw new Error('Pass raw YAML text (utf8 string), not a parsed object or Buffer');
}
throw e;
} Prevention
- Read files with encoding: fs.readFileSync(path, 'utf8')
- Never pass an already-parsed object to a text-based validator
- Assert typeof doc === 'string' at the call site during development
When it happens
Trigger: Calling validator.validate(doc, target) with a non-string doc — e.g. an already-parsed JS object, a Buffer from fs.readFileSync, or undefined when a file read failed.
Common situations: Passing the result of YAML.parse to a validator that expects raw text; reading a file without .toString('utf8'); a variable being undefined because the file didn't load.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- result.substring(__RESULT_ERR_PREFIX.length)
- Flow modules must be an array
- Flow groups must be an array
- Invalid group at index ${index}: must be an object
- Code parameter is required and must be a string
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/8a3303b14202b5c6.
Report an issue: GitHub.