Repository navigation
Description
Summary of the issue
cf ai to-markdown fails with [6006] Error converting to markdown. I hit it with an HTML file, but the cause applies to any file. The endpoint takes the files in a multipart field named files, and the generated command never sends a file part with that name:
--file <path>sends a file part namedfile. The API has nofilefield.--files <value>, including--files @<path>, sendsfilesas a text part.
The OpenAPI definition the commands are generated from (Forge release openapi@e2d50301) declares the field as a required array of binary strings:
"files": {
"description": "Files to convert, supplied as multipart file uploads.",
"type": "array",
"items": { "format": "binary", "type": "string" }
}The generator at 350c808 doesn't treat an array of binary strings as a file field:
isBinaryis true only for a singleformat: binaryvalue, sofilesisn't binary and the generator picks nopayloadField:
cf/packages/cli/generator/plugin/operation.ts
Line 534 in 350c808
const isBinary = isScalar(resolved, "binary"); - With no
payloadField,--filefalls back to the namefile:
const payload = info.payloadField ?? "file"; filesgoes through the branch for ordinary array fields, which appends it as a string:
cf/packages/cli/generator/plugin/emit/handler.ts
Lines 424 to 433 in 350c808
case "object": case "array": lines.push(` if (${read} !== undefined) {`); lines.push( ` const v = typeof ${read} === 'string' ? resolveFileToken(${read}, '${flag}', 'text') : ${read};` ); lines.push( ` formData.append('${f.name}', typeof v === 'string' ? v : JSON.stringify(v));` ); lines.push(" }");
#272 (the fix for #177) only added file flags for fields where isBinary is true, so this command didn't change, and 1.0.0-beta.26 fails the same way 1.0.0-beta.21 did.
A fix could treat an array whose items are format: binary as a file field and send each path as its own files part. The regression snapshot ai/to-markdown.snap in #290 records the current --file request (a part named file with application/octet-stream), so if #290 lands first, the fix will need to update that snapshot.
Expected behaviour
cf ai to-markdown uploads each file as a file part named files, with its filename, and prints the conversion result for each file. The request matches the one in the REST API docs:
curl https://api.cloudflare.com/client/v4/accounts/{ACCOUNT_ID}/ai/tomarkdown \
-X POST \
-H 'Authorization: Bearer {API_TOKEN}' \
-F "files=@cat.jpeg" \
-F "files=@somatosensory.pdf"Because files is an array, the flag should accept more than one file.
Version of cf used
1.0.0-beta.26
System information and package versions
System:
OS: Linux 7.2 Ubuntu 26.04.1 LTS 26.04.1 LTS (Resolute Raccoon)
CPU: (8) x64 Intel(R) Core(TM) i5-10310U CPU @ 1.70GHz
Memory: 12.06 GB / 15.25 GB
Container: Yes
Shell: 5.3.9 - /bin/bash
Binaries:
Node: 26.13.0 - /home/hjkl/.local/share/mise/installs/node/26.13.0/bin/node
Yarn: 4.18.1 - /home/hjkl/.local/share/vite-plus/fallback-bin/yarn
npm: 11.20.0 - /home/hjkl/.local/share/mise/installs/node/26.13.0/bin/npm
pnpm: 12.16.1 - /home/hjkl/.local/share/mise/installs/pnpm/12.16.1/pnpm
bun: 1.4.4 - /home/hjkl/.local/share/vite-plus/fallback-bin/bun
Deno: 2.9.8 - /home/hjkl/.local/share/mise/installs/deno/2.9.8/bin/deno
npmPackages:
@cloudflare/vite-plugin: 2.0.0-beta.v.8 => 2.0.0-beta.v.8
cf: 1.0.0-beta.26 => 1.0.0-beta.26
Reproduction (optional)
printf '<h1>Hello</h1>\n' > sample.html
cf ai to-markdown --file sample.html
cf ai to-markdown --files @sample.htmlBoth commands fail with 6006. cf ai list-markdown-supported-formats lists .html with text/html, and HTML conversion through the Workers AI binding (env.AI.toMarkdown()) works in my Worker.
To see what cf sends, I pointed CLOUDFLARE_API_BASE_URL at a local server that parses the multipart body and prints each part. The first line below comes from --file, the second from --files @sample.html:
part "file": file name="sample.html" type="application/octet-stream" content="<h1>Hello</h1>\n"
part "files": text "<h1>Hello</h1>\r\n"
Relevant error logs (optional)
┌ APIError
│ [6006] Error converting to markdown
│ 400 Bad Request · HTTP /accounts/<account-id>/ai/tomarkdown
└
Activity