feat(sdk): give Docker-not-running error an actionable next step (#20280)
## Summary The current Docker-not-running message is unhelpful in two ways: 1. It doesn't tell users **how** to start Docker 2. "try again" is meaningless because a first-time user doesn't yet know the command they just ran (they got here from `create-twenty-app`, not from typing `yarn twenty server start` themselves) **Before:** ``` Docker is not running. Please start Docker and try again. ``` **After (macOS example):** ``` Docker is not running. Start Docker: Run: open -a Docker (or launch Docker Desktop from Applications) Then retry: yarn twenty server start Don't have Docker? Install from https://docs.docker.com/get-docker/ ``` The platform-specific line is detected via `process.platform`: - `darwin` → `open -a Docker` + Docker Desktop fallback - `linux` → `sudo systemctl start docker` + Docker Desktop fallback - `win32` → "Launch Docker Desktop from the Start menu" - other → link to install docs The retry command is computed at the call site so it preserves the user's actual flags — `yarn twenty server start --test`, `yarn twenty server upgrade 2.2.0 --test`, etc. ## Why This came out of shadowing a first-time app developer who hit this error during `npx create-twenty-app`. They were stuck — the CLI told them to "try again" but they had only learned two commands so far (`create-twenty-app` and `yarn dev`), neither of which was the right one. Improving the message turns the error into a teaching moment. ## Test plan - [x] `npx nx typecheck twenty-sdk` passes - [x] `npx nx lint twenty-sdk` passes - [x] Manually verified rendered output for both `server start` and `server upgrade` flows on macOS - [ ] Verify message renders correctly on Linux/Windows in practice ## Possible follow-ups (out of scope) - Auto-launch Docker Desktop on macOS if installed (changes user state — separate PR) - Make the multi-line CLI error printer style only the first line in red, so guidance reads as default text rather than red Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -9,6 +9,7 @@ import {
|
||||
DEFAULT_PORT,
|
||||
DEFAULT_TEST_PORT,
|
||||
getContainerPort,
|
||||
getDockerNotRunningMessage,
|
||||
IMAGE,
|
||||
isContainerRunning,
|
||||
TEST_CONTAINER_NAME,
|
||||
@@ -148,11 +149,15 @@ const innerServerStart = async (
|
||||
}
|
||||
|
||||
if (!checkDockerRunning()) {
|
||||
const retryCommand = isTest
|
||||
? 'yarn twenty server start --test'
|
||||
: 'yarn twenty server start';
|
||||
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
code: SERVER_ERROR_CODES.DOCKER_NOT_RUNNING,
|
||||
message: 'Docker is not running. Please start Docker and try again.',
|
||||
message: getDockerNotRunningMessage(retryCommand),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
containerExists,
|
||||
getContainerDigest,
|
||||
getContainerPort,
|
||||
getDockerNotRunningMessage,
|
||||
getImageDigest,
|
||||
getImageForVersion,
|
||||
TEST_CONTAINER_NAME,
|
||||
@@ -30,11 +31,19 @@ const innerServerUpgrade = async (
|
||||
const { version = 'latest', test: isTest, onProgress } = options;
|
||||
|
||||
if (!checkDockerRunning()) {
|
||||
const retryCommand = [
|
||||
'yarn twenty server upgrade',
|
||||
version !== 'latest' ? version : null,
|
||||
isTest ? '--test' : null,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(' ');
|
||||
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
code: SERVER_ERROR_CODES.DOCKER_NOT_RUNNING,
|
||||
message: 'Docker is not running. Please start Docker and try again.',
|
||||
message: getDockerNotRunningMessage(retryCommand),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -103,3 +103,29 @@ export const checkDockerRunning = (): boolean => {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const getDockerStartInstruction = (): string => {
|
||||
switch (process.platform) {
|
||||
case 'darwin':
|
||||
return ' Run: open -a Docker\n (or launch Docker Desktop from Applications)';
|
||||
case 'linux':
|
||||
return ' Run: sudo systemctl start docker\n (or launch Docker Desktop if installed)';
|
||||
case 'win32':
|
||||
return ' Launch Docker Desktop from the Start menu';
|
||||
default:
|
||||
return ' See https://docs.docker.com/engine/install/ for installation';
|
||||
}
|
||||
};
|
||||
|
||||
export const getDockerNotRunningMessage = (retryCommand: string): string =>
|
||||
[
|
||||
'Docker is not running.',
|
||||
'',
|
||||
'Start Docker:',
|
||||
getDockerStartInstruction(),
|
||||
'',
|
||||
'Then retry:',
|
||||
` ${retryCommand}`,
|
||||
'',
|
||||
"Don't have Docker? Install from https://docs.docker.com/get-docker/",
|
||||
].join('\n');
|
||||
|
||||
Reference in New Issue
Block a user