-
-
Notifications
You must be signed in to change notification settings - Fork 4
Open
Labels
bugSomething isn't workingSomething isn't working
Description
Bug Description
Never opens a websocket, axios errors out with 400
To Reproduce
Steps to reproduce the behavior:
- Run command 'termly-dev start --ai opencode --debug'
- See error
Expected Behavior
Expected to register pairing code
Actual Behavior
Errors out with:
❌ Failed to register pairing code: Request failed with status code 400
❌ Unexpected error: Request failed with status code 400
Environment
- OS: macOS 26.2
- Node.js version: v25.2.1
- Termly CLI version: 1.7.0
- AI tool: Opencode
- Environment: both Production and Development
Logs
Click to expand logs
Console logs:
[DEBUG] Checking version: @termly-dev/cli-dev@1.7.0
[DEBUG] Version check failed: Request failed with status code 400
[DEBUG] Working directory: /Users/###/###/###
[DEBUG] Project name: Manager
[DEBUG] Manual tool selection: opencode
Using OpenCode v1.1.53
[DEBUG] Pairing code generated: ###
[DEBUG] Public key generated: ###...
ℹ Environment: Development
[DEBUG] Server URL: wss://dev-api.termly.dev
[DEBUG] API URL: https://dev-api.termly.dev
[DEBUG] Registering pairing code: ###
❌ Failed to register pairing code: Request failed with status code 400
❌ Unexpected error: Request failed with status code 400
AxiosError: Request failed with status code 400
at settle (/Users/###/.nvm/versions/node/v25.2.1/lib/node_modules/@termly-dev/cli-dev/node_modules/axios/dist/node/axios.cjs:2151:12)
at IncomingMessage.handleStreamEnd (/Users/###/.nvm/versions/node/v25.2.1/lib/node_modules/@termly-dev/cli-dev/node_modules/axios/dist/node/axios.cjs:3545:11)
at IncomingMessage.emit (node:events:520:35)
at endReadableNT (node:internal/streams/readable:1701:12)
at process.processTicksAndRejections (node:internal/process/task_queues:89:21)
at Axios.request (/Users/###/.nvm/versions/node/v25.2.1/lib/node_modules/@termly-dev/cli-dev/node_modules/axios/dist/node/axios.cjs:4796:41)
at process.processTicksAndRejections (node:internal/process/task_queues:103:5)
at async registerPairingCode (/Users/###/.nvm/versions/node/v25.2.1/lib/node_modules/@termly-dev/cli-dev/lib/commands/start.js:47:22)
at async startCommand (/Users/###/.nvm/versions/node/v25.2.1/lib/node_modules/@termly-dev/cli-dev/lib/commands/start.js:129:5)
at async Command.<anonymous> (/Users/###/.nvm/versions/node/v25.2.1/lib/node_modules/@termly-dev/cli-dev/bin/cli-dev.js:42:5) {
isAxiosError: true,
code: 'ERR_BAD_REQUEST',
config: {
transitional: {
silentJSONParsing: true,
forcedJSONParsing: true,
clarifyTimeoutError: false,
legacyInterceptorReqResOrdering: true
},
adapter: [ 'xhr', 'http', 'fetch' ],
transformRequest: [ [Function: transformRequest] ],
transformResponse: [ [Function: transformResponse] ],
timeout: 0,
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
maxBodyLength: -1,
env: { FormData: [Function], Blob: [class Blob] },
validateStatus: [Function: validateStatus],
headers: Object [AxiosHeaders] {
Accept: 'application/json, text/plain, */*',
'Content-Type': 'application/json',
'X-API-Type': 'cli',
'User-Agent': 'axios/1.13.5',
'Content-Length': '547',
'Accept-Encoding': 'gzip, compress, deflate, br'
},
method: 'post',
url: 'https://dev-api.termly.dev/api/pairing',
data: '{"code":"###","publicKey":"###","projectName":"###","workingDir":"/Users/###/###/###","computerName":"###-MacBook-Pro-2.local","aiTool":"opencode","aiToolVersion":"1.1.53"}',
allowAbsoluteUrls: true }, request: <ref *1> ClientRequest { _events: [Object: null prototype] { abort: [Function (anonymous)], aborted: [Function (anonymous)],
connect: [Function (anonymous)],
error: [Function (anonymous)],
socket: [Function (anonymous)],
timeout: [Function (anonymous)],
finish: [Function: requestOnFinish]
},
_eventsCount: 7,
_maxListeners: undefined,
outputData: [],
outputSize: 0,
writable: true,
destroyed: false,
_last: false,
chunkedEncoding: false,
shouldKeepAlive: false,
maxRequestsOnConnectionReached: false,
_defaultKeepAlive: true,
useChunkedEncodingByDefault: true,
sendDate: false,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
strictContentLength: false,
_contentLength: 547,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
_closed: false,
_header: 'POST https://dev-api.termly.dev/api/pairing HTTP/1.1\r\n' +
'Accept: application/json, text/plain, */*\r\n' +
'Content-Type: application/json\r\n' +
'X-API-Type: cli\r\n' +
'User-Agent: axios/1.13.5\r\n' +
'Content-Length: 547\r\n' +
'Accept-Encoding: gzip, compress, deflate, br\r\n' +
'host: dev-api.termly.dev\r\n' +
'Connection: keep-alive\r\n' +
'\r\n',
_keepAliveTimeout: 0,
_onPendingData: [Function: nop],
agent: Agent {
_events: [Object: null prototype],
_eventsCount: 2,
_maxListeners: undefined,
options: [Object: null prototype],
defaultPort: 80,
protocol: 'http:',
requests: [Object: null prototype] {},
sockets: [Object: null prototype],
freeSockets: [Object: null prototype] {},
keepAliveMsecs: 1000,
keepAlive: true,
maxSockets: Infinity,
maxFreeSockets: 256,
scheduling: 'lifo',
maxTotalSockets: Infinity,
totalSocketCount: 1,
agentKeepAliveTimeoutBuffer: 1000,
Symbol(shapeMode): false,
Symbol(kCapture): false
},
socketPath: undefined,
method: 'POST',
maxHeaderSize: undefined,
insecureHTTPParser: undefined,
joinDuplicateHeaders: undefined,
path: 'https://dev-api.termly.dev/api/pairing',
_ended: true,
res: IncomingMessage {
_events: [Object],
_readableState: [ReadableState],
_maxListeners: undefined,
socket: [Socket],
httpVersionMajor: 1,
httpVersionMinor: 1,
httpVersion: '1.1',
complete: true,
rawHeaders: [Array],
rawTrailers: [],
joinDuplicateHeaders: undefined,
aborted: false,
upgrade: false,
url: '',
method: null,
statusCode: 400,
statusMessage: 'Invalid header received from client',
client: [Socket],
_consuming: true,
_dumped: false,
req: [Circular *1],
_eventsCount: 4,
responseUrl: 'https://dev-api.termly.dev/api/pairing',
redirects: [],
Symbol(shapeMode): true,
Symbol(kCapture): false,
Symbol(kHeaders): [Object],
Symbol(kHeadersCount): 4,
Symbol(kTrailers): null,
Symbol(kTrailersCount): 0
},
aborted: false,
timeoutCb: [Function: emitRequestTimeout],
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
reusedSocket: false,
host: 'localhost',
protocol: 'http:', _redirectable: Writable { _events: [Object], _writableState: [WritableState], _maxListeners: undefined, _options: [Object],
_ended: true,
_ending: true,
_redirectCount: 0,
_redirects: [],
_requestBodyLength: 547,
_requestBodyBuffers: [],
_eventsCount: 3,
_onNativeResponse: [Function (anonymous)],
_currentRequest: [Circular *1],
_currentUrl: 'https://dev-api.termly.dev/api/pairing',
_timeout: null,
Symbol(shapeMode): true,
Symbol(kCapture): false
},
Symbol(shapeMode): false,
Symbol(kCapture): false,
Symbol(kBytesWritten): 0,
Symbol(kNeedDrain): false,
Symbol(corked): 0,
Symbol(kChunkedBuffer): [],
Symbol(kChunkedLength): 0,
Symbol(kSocket): Socket {
connecting: false,
_hadError: false,
_parent: null,
_host: 'localhost',
_closeAfterHandlingError: false,
_events: [Object],
_readableState: [ReadableState],
_writableState: [WritableState],
allowHalfOpen: false,
_maxListeners: undefined,
_eventsCount: 8,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: null,
_server: null,
timeout: 0,
parser: null,
_httpMessage: [Circular *1],
autoSelectFamilyAttemptedAddresses: [Array],
write: [Function: writeAfterFIN],
Symbol(async_id_symbol): 83,
Symbol(kHandle): null,
Symbol(lastWriteQueueSize): 0,
Symbol(timeout): Timeout {
_idleTimeout: -1,
_idlePrev: null,
_idleNext: null,
_idleStart: 1020,
_onTimeout: null,
_timerArgs: undefined,
_repeat: null,
_destroyed: true,
Symbol(refed): false,
Symbol(kHasPrimitive): false,
Symbol(asyncId): 74,
Symbol(triggerId): 0,
Symbol(kAsyncContextFrame): undefined
},
Symbol(kBuffer): null,
Symbol(kBufferCb): null,
Symbol(kBufferGen): null,
Symbol(shapeMode): true,
Symbol(kCapture): false,
Symbol(kSetNoDelay): true,
Symbol(kSetKeepAlive): true,
Symbol(kSetKeepAliveInitialDelay): 60,
Symbol(kBytesRead): 134,
Symbol(kBytesWritten): 838
},
Symbol(kOutHeaders): [Object: null prototype] {
accept: [Array],
'content-type': [Array],
'x-api-type': [Array],
'user-agent': [Array],
'content-length': [Array],
'accept-encoding': [Array],
host: [Array]
},
Symbol(errored): null,
Symbol(kHighWaterMark): 65536,
Symbol(kRejectNonStandardBodyWrites): false,
Symbol(kUniqueHeaders): null
},
response: {
status: 400,
statusText: 'Invalid header received from client',
headers: Object [AxiosHeaders] {
'content-type': 'text/plain',
connection: 'close'
},
config: {
transitional: [Object],
adapter: [Array],
transformRequest: [Array],
transformResponse: [Array],
timeout: 0,
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
maxBodyLength: -1,
env: [Object],
validateStatus: [Function: validateStatus],
headers: [Object [AxiosHeaders]],
method: 'post',
url: 'https://dev-api.termly.dev/api/pairing',
data: '{"code":"###","publicKey":"###","projectName":"###","workingDir":"/Users/###/###/###","computerName":"###-MacBook-Pro-2.local","aiTool":"opencode","aiToolVersion":"1.1.53"}',
allowAbsoluteUrls: true }, request: <ref *1> ClientRequest { _events: [Object: null prototype], _eventsCount: 7, _maxListeners: undefined,
outputData: [],
outputSize: 0,
writable: true,
destroyed: false,
_last: false,
chunkedEncoding: false,
shouldKeepAlive: false,
maxRequestsOnConnectionReached: false,
_defaultKeepAlive: true,
useChunkedEncodingByDefault: true,
sendDate: false,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
strictContentLength: false,
_contentLength: 547,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
_closed: false,
_header: 'POST https://dev-api.termly.dev/api/pairing HTTP/1.1\r\n' +
'Accept: application/json, text/plain, */*\r\n' +
'Content-Type: application/json\r\n' +
'X-API-Type: cli\r\n' +
'User-Agent: axios/1.13.5\r\n' +
'Content-Length: 547\r\n' +
'Accept-Encoding: gzip, compress, deflate, br\r\n' +
'host: dev-api.termly.dev\r\n' +
'Connection: keep-alive\r\n' +
'\r\n',
_keepAliveTimeout: 0,
_onPendingData: [Function: nop],
agent: [Agent],
socketPath: undefined,
method: 'POST',
maxHeaderSize: undefined,
insecureHTTPParser: undefined,
joinDuplicateHeaders: undefined,
path: 'https://dev-api.termly.dev/api/pairing',
_ended: true,
res: [IncomingMessage],
aborted: false,
timeoutCb: [Function: emitRequestTimeout],
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
reusedSocket: false,
host: 'localhost',
protocol: 'http:',
_redirectable: [Writable],
Symbol(shapeMode): false,
Symbol(kCapture): false,
Symbol(kBytesWritten): 0, Symbol(kNeedDrain): false,
Symbol(corked): 0, Symbol(kChunkedBuffer): [],
Symbol(kChunkedLength): 0,
Symbol(kSocket): [Socket],
Symbol(kOutHeaders): [Object: null prototype],
Symbol(errored): null, Symbol(kHighWaterMark): 65536,
Symbol(kRejectNonStandardBodyWrites): false,
Symbol(kUniqueHeaders): null },
data: 'Invalid header received from client.\n' },
status: 400 }
Logs from ~/.termly/logs/cli.log:
[2026-02-09 18:51:30] DEBUG: Checking version: @termly-dev/cli-dev@1.7.0
[2026-02-09 18:51:30] DEBUG: Version check failed: Request failed with status code 400
[2026-02-09 18:51:30] DEBUG: Working directory: /Users/###/###/###
[2026-02-09 18:51:30] DEBUG: Project name: Manager
[2026-02-09 18:51:30] DEBUG: Manual tool selection: opencode
[2026-02-09 18:51:31] DEBUG: Pairing code generated: ###
[2026-02-09 18:51:31] DEBUG: Public key generated: ###...
[2026-02-09 18:51:31] INFO: Environment: Development
[2026-02-09 18:51:31] DEBUG: Server URL: wss://dev-api.termly.dev
[2026-02-09 18:51:31] DEBUG: API URL: https://dev-api.termly.dev
[2026-02-09 18:51:31] DEBUG: Registering pairing code: ###
[2026-02-09 18:51:31] ERROR: Failed to register pairing code: Request failed with status code 400
[2026-02-09 18:51:31] ERROR: Unexpected error: Request failed with status code 400
Additional Context
See logs. Could be a dependency version issue
Possible Solution
If you have ideas about what might be causing this or how to fix it, please share!
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working