Skip to content

fix: message send and navigator message send fail at parse with Invalid argument spec - #3

Open
viniciuscffreitas wants to merge 1 commit into
Linked-API:mainfrom
viniciuscffreitas:fix/message-send-arg-spec
Open

fix: message send and navigator message send fail at parse with Invalid argument spec#3
viniciuscffreitas wants to merge 1 commit into
Linked-API:mainfrom
viniciuscffreitas:fix/message-send-arg-spec

Conversation

@viniciuscffreitas

Copy link
Copy Markdown

What is broken

linkedin message send and linkedin navigator message send do not run at all. Every invocation, including the exact examples in the README, stops at argument parsing:

$ linkedin message send https://www.linkedin.com/in/john-doe "Hello John!"
 ›   Error: Invalid argument spec:
 ›   person-url (optional)  LinkedIn profile URL of the recipient (omit when
 ›                          --thread-id is provided)
 ›   text (required)        Message text (up to 1900 characters)

Reproduced on the published @linkedapi/linkedin-cli@1.2.7 and on a clean build of main. The command never reaches the API, so sending a message through the CLI is not possible today.

Cause

oclif requires every optional argument to be declared after the required ones. Both commands declare the optional person-url before the required text, so oclif rejects the spec before parsing anything. I scanned all 71 commands and only these two files have the pattern.

Why relaxing required is not enough

Making text optional on its own creates a worse bug. With --thread-id and one positional, oclif binds that positional to person-url, so the CLI would call the API with the message body in the recipient field and no text at all. Nothing would fail loudly.

Both positionals are now declared optional and bound explicitly in a small helper, resolveMessagePositionals. When --thread-id is present and only one positional was given, that positional is the message text. A missing text is now rejected with the validation exit code instead of sending an empty message.

Verification

Captured the outgoing request body against a local mock of the API, so no LinkedIn traffic was involved:

$ linkedin message send https://www.linkedin.com/in/john-doe "Hello John!"
{"actionType":"st.sendMessage","personUrl":"https://www.linkedin.com/in/john-doe","text":"Hello John!"}

$ linkedin message send --thread-id 2-abc123 "Sounds good, talk soon!"
{"actionType":"st.sendMessage","threadId":"2-abc123","text":"Sounds good, talk soon!"}

$ linkedin navigator message send --thread-id 2-abc123 "Reply text"
{"actionType":"nv.sendMessage","threadId":"2-abc123","text":"Reply text"}

$ linkedin navigator message send https://www.linkedin.com/in/john-doe "Hi there" --subject "Partnership"
{"actionType":"nv.sendMessage","personUrl":"https://www.linkedin.com/in/john-doe","text":"Hi there","subject":"Partnership"}

The second and third lines are the point: the lone positional lands in text and no personUrl is sent.

Tests

Added test/message-send-args.test.js with 7 cases covering both commands: the documented two positional form, the --thread-id form, and the rejection paths. All 7 fail on current main and pass with this change. They run the built CLI as a child process with an empty config directory and an unreachable API base URL, so they stop at the authentication check and can never produce outbound traffic.

The repo had no test script, so I added one using the Node built in test runner. No new dependency:

"test": "npm run build && node --test test/*.test.js"

npm run typecheck, npm run lint and npm run build are all clean.

Scope

Only this defect. I left the existing behavior where action level errors exit 0 with {success: false} untouched, since CLAUDE.md documents that as intended.

Both `message send` and `navigator message send` failed at parse time with
"Invalid argument spec" and never reached the API. oclif requires every
optional argument to be declared after the required ones, and both commands
declare the optional `person-url` before the required `text`.

Declaring `text` as optional alone is not enough: with `--thread-id` and a
single positional, oclif binds that positional to `person-url`, so the CLI
would send an empty message. Both positionals are now declared optional and
bound in `resolveMessagePositionals`, which maps a lone positional to the
message text when `--thread-id` is present. A missing text is rejected with
exit code 5 instead of silently sending nothing.

Adds a test suite covering both commands and an `npm test` script using the
Node built-in test runner, so no new dependency is introduced.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant