Skip to content

Commit 049af23

Browse files
committed
fix(dlx-package): add comprehensive error handling for package installation
Improve error messages for package installation failures: - E404/ETARGET: Package not found with npm registry link - ENOTFOUND/ETIMEDOUT: Network errors with connectivity guidance - EACCES/EPERM: Permission denied with directory path and fix suggestions - EROFS: Read-only filesystem with SOCKET_DLX_DIR configuration hint Users now get actionable guidance for common installation failures instead of generic errors.
1 parent 45a6daf commit 049af23

1 file changed

Lines changed: 58 additions & 11 deletions

File tree

src/dlx-package.ts

Lines changed: 58 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
*
1212
* Concurrency protection:
1313
* - Uses process-lock to prevent concurrent installation corruption
14-
* - Lock file created at ~/.socket/_dlx/<hash>/.lock
15-
* - Aligned with npm npx's concurrency.lock strategy (5s stale, 2s touching)
14+
* - Lock file created at ~/.socket/_dlx/<hash>/concurrency.lock
15+
* - Uses npm npx's concurrency.lock naming convention (5s stale, 2s touching)
1616
* - Prevents multiple processes from corrupting the same package installation
1717
*
1818
* Version range handling:
@@ -140,9 +140,34 @@ async function ensurePackageInstalled(
140140
path.join(packageDir, 'node_modules', packageName),
141141
)
142142

143+
// Ensure package directory exists before creating lock.
144+
// The lock directory will be created inside this directory.
145+
try {
146+
await fs.mkdir(packageDir, { recursive: true })
147+
} catch (e) {
148+
const code = (e as NodeJS.ErrnoException).code
149+
if (code === 'EACCES' || code === 'EPERM') {
150+
throw new Error(
151+
`Permission denied creating package directory: ${packageDir}\n` +
152+
'Please check directory permissions or run with appropriate access.',
153+
{ cause: e },
154+
)
155+
}
156+
if (code === 'EROFS') {
157+
throw new Error(
158+
`Cannot create package directory on read-only filesystem: ${packageDir}\n` +
159+
'Ensure the filesystem is writable or set SOCKET_DLX_DIR to a writable location.',
160+
{ cause: e },
161+
)
162+
}
163+
throw new Error(`Failed to create package directory: ${packageDir}`, {
164+
cause: e,
165+
})
166+
}
167+
143168
// Use process lock to prevent concurrent installations.
144-
// Similar to npm npx's concurrency.lock approach.
145-
const lockPath = path.join(packageDir, '.lock')
169+
// Uses npm npx's concurrency.lock naming convention.
170+
const lockPath = path.join(packageDir, 'concurrency.lock')
146171

147172
return await processLock.withLock(
148173
lockPath,
@@ -157,16 +182,38 @@ async function ensurePackageInstalled(
157182
}
158183
}
159184

160-
// Ensure package directory exists.
161-
await fs.mkdir(packageDir, { recursive: true })
162-
163185
// Use pacote to extract the package.
164186
// Pacote leverages npm cache when available but doesn't require npm CLI.
165187
const pacoteCachePath = getPacoteCachePath()
166-
await pacote.extract(packageSpec, installedDir, {
167-
// Use consistent pacote cache path (respects npm cache locations when available).
168-
cache: pacoteCachePath || path.join(packageDir, '.cache'),
169-
})
188+
try {
189+
await pacote.extract(packageSpec, installedDir, {
190+
// Use consistent pacote cache path (respects npm cache locations when available).
191+
cache: pacoteCachePath || path.join(packageDir, '.cache'),
192+
})
193+
} catch (e) {
194+
const code = (e as any).code
195+
if (code === 'E404' || code === 'ETARGET') {
196+
throw new Error(
197+
`Package not found: ${packageSpec}\n` +
198+
'Verify the package exists on npm registry and check the version.\n' +
199+
`Visit https://www.npmjs.com/package/${packageName} to see available versions.`,
200+
{ cause: e },
201+
)
202+
}
203+
if (code === 'ENOTFOUND' || code === 'ETIMEDOUT' || code === 'EAI_AGAIN') {
204+
throw new Error(
205+
`Network error installing ${packageSpec}\n` +
206+
'Check your internet connection and try again.',
207+
{ cause: e },
208+
)
209+
}
210+
throw new Error(
211+
`Failed to install package: ${packageSpec}\n` +
212+
`Destination: ${installedDir}\n` +
213+
'Check npm registry connectivity or package name.',
214+
{ cause: e },
215+
)
216+
}
170217

171218
return { installed: true, packageDir }
172219
},

0 commit comments

Comments
 (0)