Summary
Three related issues encountered when uploading images to Feishu documents via lark-cli 1.0.31. The dedicated docs +media-insert subcommand works when all workarounds are applied, but the friction is high and error messages are unhelpful.
Environment
- lark-cli version: 1.0.31 (1.0.68 available but not yet installed)
- OS: Linux x86_64 (WSL2, kernel 6.6.87.2)
- Node: v22.22.2
- Install method:
npm install -g @larksuite/cli
- Auth: User token (authorized via
lark-cli auth login)
Issue 1: --file rejects absolute paths
Description
The --file flag refuses absolute paths with a security error, requiring relative paths within the current working directory only.
Reproduction
# Using an absolute path
lark-cli docs +media-insert \
--file /home/user/images/img1.jpg \
--doc R0HZdzpxPoaqESx7Dm1cDzTanFc \
--type image \
--as user
Error
{
"ok": false,
"error": {
"type": "validation",
"message": "unsafe file path: --file must be a relative path within the current directory, got \"/home/user/images/img1.jpg\" (hint: cd to the target directory first, or use a relative path like ./filename)"
}
}
Expected behavior
Absolute paths should be accepted. Standard CLI tools (curl -F, gh, aws-cli, etc.) all accept absolute paths. The current restriction adds unnecessary friction — users must cd to the file's directory before every upload.
Workaround
cd to the directory and use ./img1.jpg instead.
Issue 2: lark-cli api generic mode: --file doesn't send required file_name/size form fields for drive/v1/medias/upload_all
Description
The Feishu upload_all API requires file_name, parent_type, parent_node, and size as multipart form fields alongside the file. When using the generic lark-cli api POST mode with --file, these fields are not auto-populated. Even when passing them via --data, the dry-run shows them as form_fields but the actual request still fails with 1061002 params error.
Reproduction
cd /home/user/images
# Attempt 1: --file only, no file_name/size
lark-cli api POST /open-apis/drive/v1/medias/upload_all \
--file ./img2.jpg \
--params '{"parent_node":"doxcnfN5mNGQQlr3VStFabiKzJg","parent_type":"docx_image"}' \
--as user
Error (Attempt 1)
{
"ok": false,
"error": {
"type": "api_error",
"code": 1061002,
"message": "API error: [1061002] params error."
}
}
# Attempt 2: Add --data with file_name and size
lark-cli api POST /open-apis/drive/v1/medias/upload_all \
--file ./img2.jpg \
--params '{"parent_node":"doxcnfN5mNGQQlr3VStFabiKzJg","parent_type":"docx_image"}' \
--data '{"file_name":"img2.jpg","size":115295}' \
--as user
Dry-run output (Attempt 2)
{
"body": {
"file": { "field": "file", "path": "./img2.jpg" },
"form_fields": { "file_name": "img2.jpg", "size": 115295 },
"options": ["WithFileUpload"]
}
}
Error (Attempt 2 — actual execution)
{
"ok": false,
"error": {
"type": "api_error",
"code": 1061002,
"message": "API error: [1061002] params error."
}
}
Despite form_fields appearing in the dry-run, the actual multipart request apparently doesn't include them correctly, or they're not sent as multipart form fields alongside the file.
Expected behavior
Either:
--file should auto-populate file_name (from the filename) and size (from os.Stat) when the target API is drive/v1/medias/upload_all, OR
--data fields should be correctly sent as multipart form fields when --file triggers multipart mode
Note
The dedicated docs +media-upload subcommand handles this correctly — it auto-populates file_name and size:
lark-cli docs +media-upload \
--file ./img3.jpg \
--parent-type docx_image \
--doc-id R0HZdzpxPoaqESx7Dm1cDzTanFc \
--parent-node doxcnfN5mNGQQlr3VStFabiKzJg \
--as user
# → ok: true, file_token returned
But users who need the generic lark-cli api mode (e.g. for APIs without a dedicated subcommand) are stuck.
Issue 3: Default bot identity causes cryptic 1770032 forBidden on user-created documents
Description
When a document is created with --as user, subsequent docs +media-insert calls default to bot identity and fail with a cryptic 1770032 forBidden error. The error message doesn't hint at the identity mismatch.
Reproduction
# Step 1: Create document as user
lark-cli docs +create --as user --title "Test Doc"
# → document_id: R0HZdzpxPoaqESx7Dm1cDzTanFc
# Step 2: Insert image (defaults to bot identity)
cd /home/user/images
lark-cli docs +media-insert \
--file ./img1.jpg \
--doc R0HZdzpxPoaqESx7Dm1cDzTanFc \
--type image
Error
{
"ok": false,
"identity": "bot",
"error": {
"type": "api_error",
"code": 1770032,
"message": "API call failed: [1770032] forBidden",
"detail": {
"log_id": "20260713015444146076E0FED09D3BE020"
}
}
}
Expected behavior
One of:
- Auto-detect: If the document was created by a user, default to
user identity for subsequent operations on that document
- Better error message: Include a hint like "This document was created with user identity. Try adding
--as user."
- Remember identity: If the last
docs +create used --as user, default subsequent docs * calls to user as well
Workaround
Explicitly pass --as user:
lark-cli docs +media-insert \
--file ./img1.jpg \
--doc R0HZdzpxPoaqESx7Dm1cDzTanFc \
--type image \
--as user
# → ok: true
Impact
These three issues combine to make image upload to Feishu documents frustrating:
- Can't use absolute paths → must
cd first
- Generic API mode broken for multipart uploads → must use specific subcommands
- Silent identity mismatch → must remember
--as user on every command
A user following the natural flow (create doc → upload image) will hit at least 2 of these 3 issues.
Suggested improvements
| Issue |
Suggestion |
| Absolute path rejection |
Accept absolute paths, or at minimum resolve them after a security check (e.g. reject ../ escapes but allow /absolute/paths) |
Generic API --file missing form fields |
Auto-populate file_name from filename and size from os.Stat when --file is used, or document that --data fields are sent as JSON body (not multipart form fields) |
| Bot identity default |
Improve error message to suggest --as user, or auto-detect document owner identity |
Summary
Three related issues encountered when uploading images to Feishu documents via lark-cli 1.0.31. The dedicated
docs +media-insertsubcommand works when all workarounds are applied, but the friction is high and error messages are unhelpful.Environment
npm install -g @larksuite/clilark-cli auth login)Issue 1:
--filerejects absolute pathsDescription
The
--fileflag refuses absolute paths with a security error, requiring relative paths within the current working directory only.Reproduction
# Using an absolute path lark-cli docs +media-insert \ --file /home/user/images/img1.jpg \ --doc R0HZdzpxPoaqESx7Dm1cDzTanFc \ --type image \ --as userError
{ "ok": false, "error": { "type": "validation", "message": "unsafe file path: --file must be a relative path within the current directory, got \"/home/user/images/img1.jpg\" (hint: cd to the target directory first, or use a relative path like ./filename)" } }Expected behavior
Absolute paths should be accepted. Standard CLI tools (
curl -F,gh,aws-cli, etc.) all accept absolute paths. The current restriction adds unnecessary friction — users mustcdto the file's directory before every upload.Workaround
cdto the directory and use./img1.jpginstead.Issue 2:
lark-cli apigeneric mode:--filedoesn't send requiredfile_name/sizeform fields fordrive/v1/medias/upload_allDescription
The Feishu
upload_allAPI requiresfile_name,parent_type,parent_node, andsizeas multipart form fields alongside the file. When using the genericlark-cli api POSTmode with--file, these fields are not auto-populated. Even when passing them via--data, the dry-run shows them asform_fieldsbut the actual request still fails with1061002 params error.Reproduction
Error (Attempt 1)
{ "ok": false, "error": { "type": "api_error", "code": 1061002, "message": "API error: [1061002] params error." } }Dry-run output (Attempt 2)
{ "body": { "file": { "field": "file", "path": "./img2.jpg" }, "form_fields": { "file_name": "img2.jpg", "size": 115295 }, "options": ["WithFileUpload"] } }Error (Attempt 2 — actual execution)
{ "ok": false, "error": { "type": "api_error", "code": 1061002, "message": "API error: [1061002] params error." } }Despite
form_fieldsappearing in the dry-run, the actual multipart request apparently doesn't include them correctly, or they're not sent as multipart form fields alongside the file.Expected behavior
Either:
--fileshould auto-populatefile_name(from the filename) andsize(fromos.Stat) when the target API isdrive/v1/medias/upload_all, OR--datafields should be correctly sent as multipart form fields when--filetriggers multipart modeNote
The dedicated
docs +media-uploadsubcommand handles this correctly — it auto-populatesfile_nameandsize:lark-cli docs +media-upload \ --file ./img3.jpg \ --parent-type docx_image \ --doc-id R0HZdzpxPoaqESx7Dm1cDzTanFc \ --parent-node doxcnfN5mNGQQlr3VStFabiKzJg \ --as user # → ok: true, file_token returnedBut users who need the generic
lark-cli apimode (e.g. for APIs without a dedicated subcommand) are stuck.Issue 3: Default
botidentity causes cryptic1770032 forBiddenon user-created documentsDescription
When a document is created with
--as user, subsequentdocs +media-insertcalls default tobotidentity and fail with a cryptic1770032 forBiddenerror. The error message doesn't hint at the identity mismatch.Reproduction
Error
{ "ok": false, "identity": "bot", "error": { "type": "api_error", "code": 1770032, "message": "API call failed: [1770032] forBidden", "detail": { "log_id": "20260713015444146076E0FED09D3BE020" } } }Expected behavior
One of:
useridentity for subsequent operations on that document--as user."docs +createused--as user, default subsequentdocs *calls touseras wellWorkaround
Explicitly pass
--as user:lark-cli docs +media-insert \ --file ./img1.jpg \ --doc R0HZdzpxPoaqESx7Dm1cDzTanFc \ --type image \ --as user # → ok: trueImpact
These three issues combine to make image upload to Feishu documents frustrating:
cdfirst--as useron every commandA user following the natural flow (create doc → upload image) will hit at least 2 of these 3 issues.
Suggested improvements
../escapes but allow/absolute/paths)--filemissing form fieldsfile_namefrom filename andsizefromos.Statwhen--fileis used, or document that--datafields are sent as JSON body (not multipart form fields)--as user, or auto-detect document owner identity