This document provides solutions for common issues encountered when developing or testing the Ably CLI.
Problem: Tests failing with errors about modules not being found or incorrect paths.
Example Error:
Error: Cannot find module '../commands/publish'
Solution:
- This project uses
.jsextensions in all import paths (TypeScript with ES module resolution). - Always use
.jsextensions in imports, even when importing.tssource files.
// INCORRECT — missing extension
import MyCommand from '../../src/commands/my-command'
// INCORRECT — .ts extension
import MyCommand from '../../src/commands/my-command.ts'
// CORRECT — .js extension (TypeScript resolves to .ts source)
import MyCommand from '../../src/commands/my-command.js'Problem: Tests fail with memory errors or hang indefinitely.
Example Error:
FATAL ERROR: JavaScript heap out of memory
Solution:
- Ensure all resources are properly closed, especially Ably clients:
// Always close Ably clients in tests
afterEach(async () => {
await client.close()
})
// For multiple clients, ensure all are closed
afterEach(async () => {
await Promise.all([
client1.close(),
client2.close(),
])
})- Check for unclosed connections or long-running promises that never resolve
Problem: Tests involving WebSocket connections fail or hang.
Example Error:
Timeout of 2000ms exceeded
Solution:
- For tests involving Realtime connections, be sure to mock the WebSocket properly:
// Example of properly mocking a WebSocket connection
beforeEach(() => {
// Create a fake WebSocket implementation
const fakeWebSocketInstance = {
addEventListener: vi.fn(),
removeEventListener: vi.fn(),
send: vi.fn(),
close: vi.fn(),
}
// Mock the WebSocket constructor
global.WebSocket = vi.fn().mockReturnValue(fakeWebSocketInstance) as any
})
afterEach(() => {
// Clean up
delete (global as any).WebSocket
})- Always trigger the appropriate events to simulate connection success/failure
- Don't forget to restore the original WebSocket constructor after tests
Problem: Tests involving HTTP requests fail with network errors.
Example Error:
Error: connect ECONNREFUSED
Solution:
- Use
nockorvito properly mock HTTP requests:
// Using nock for HTTP mocking
import * as nock from 'nock'
beforeEach(() => {
nock('https://control.ably.net')
.get('/v1/apps')
.reply(200, { apps: [] })
})
afterEach(() => {
nock.cleanAll()
})- Ensure all expected HTTP requests are mocked
- For control API requests, check the host being used matches the mocked domain
Problem: Unable to run the CLI locally with the ably command.
Solution:
- Link the CLI locally:
pnpm link --global
- Make sure the CLI is built before linking:
pnpm prepare && pnpm link --global
Problem: CLI not using the expected configuration.
Solution:
- View your local configuration with:
ably config show
- Find the config file location with:
ably config path
- Use environment variables to override config for testing:
ABLY_API_KEY=your_key ably channels list
- Override the config directory entirely:
ABLY_CLI_CONFIG_DIR=/path/to/custom/config ably accounts login
Problem: ESLint reporting errors that don't make sense.
Solution:
- Clear ESLint cache and try again:
pnpm exec eslint --cache --cache-location .eslintcache .
- For specific files:
pnpm exec eslint -- path/to/file.ts
Problem: TypeScript compilation errors.
Example Error:
Property 'x' does not exist on type 'Y'
Solution:
- Check that type definitions are up to date:
pnpm install @types/node@latest
- Use proper type assertions when necessary:
const result = (response as any).items as Item[]
- Add missing type definitions:
interface MyConfig { apiKey?: string controlHost?: string }
Problem: The interactive mode exits with unexpected error codes.
Solution:
- Check the exit code to understand what happened (see Exit Codes documentation and Development Stage Env Variables for interactive mode env vars)
- Common exit codes:
- Exit code 0: Wrapper (
ably-interactive) terminated normally - Exit code 42: User typed 'exit' in interactive mode (signals wrapper to terminate)
- Exit code 130: SIGINT/Ctrl+C (double Ctrl+C or force quit)
- Exit code 143: SIGTERM received
- Exit code 0: Wrapper (
Problem: Ctrl+C doesn't interrupt commands or behaves unexpectedly.
Solution:
- Use the wrapper script
ably-interactivefor better Ctrl+C handling - Single Ctrl+C should interrupt running command and return to prompt
- Double Ctrl+C (within 500ms) force quits with exit code 130
- If running without wrapper, Ctrl+C may exit the entire shell
Problem: Command history is lost between sessions.
Solution:
- Check that
~/.ably/historyfile exists and is writable - Verify the
ABLY_HISTORY_FILEenvironment variable if using custom location (runably env ABLY_HISTORY_FILEfor details) - Ensure the history file isn't exceeding size limits (default: 1000 commands, auto-trimmed at 2000 lines)
If you find errors in documentation or rules, please update them using the proper workflow and submit a pull request.
See AGENTS.md for more details on the development workflow.
- Development Stage Env Variables — Development, testing, debugging, and internal env variables. For user-facing variables, run
ably env. - Debugging Guide — Debugging tips including
DEBUG,TERMINAL_DIAGNOSTICS, and Node inspector - Testing Guide — Test layers, running tests, and debugging failures
- Exit Codes — Exit codes used by the CLI, particularly in interactive mode
- Interactive REPL — Interactive mode architecture and wrapper script design
- Auto-completion — Shell tab completion setup and troubleshooting