ruvnet/ruflo · critical
Failed to import OpenAI
Error message
Failed to import OpenAI
What it means
endpointOai(), the factory for every OpenAI-compatible endpoint in this build, lazily loads the SDK with await import("openai") and wraps any loader failure as Error("Failed to import OpenAI", { cause: e }) (endpointOai.ts:73). The real reason (module not found, ESM/CJS resolution, unsupported Node version) is on err.cause; the wrapper exists so generation code gets one recognizable error instead of raw resolver noise.
Solutions
- Inspect err.cause — it carries the actual resolution/runtime error (e.g. ERR_MODULE_NOT_FOUND, "not supported")
- Run npm ci (or npm install openai@<version from package.json>) to restore a consistent install
- Check node --version against the openai SDK's engines field and upgrade Node if needed
- If it only fails in the bundled/built app, mark the package external in the SvelteKit/Vite server config (e.g. ssr.external / server.external including "openai") so it is required at runtime from node_modules
Example fix
// before
// runtime error: Failed to import OpenAI (cause hidden)
// after (diagnose the cause, then fix the install)
try {
await (await import("openai")).OpenAI;
} catch (e) {
console.error("openai SDK failed to load:", e); // real reason: module not found / engines mismatch
process.exit(1);
}
// then: npm ci (or: npm install openai) and re-run Defensive patterns
Strategy: try-catch
Validate before calling
// fail fast at startup instead of at first generation
try {
await import("openai");
} catch (e) {
console.error("openai SDK not loadable:", e);
process.exit(1);
} Type guard
null
Try / catch
try {
const { OpenAI } = await import("openai");
} catch (e) {
throw new Error("openai dependency missing — run npm ci", { cause: e });
} Prevention
- Keep "openai" pinned in package.json and install with npm ci in CI/Docker
- Run a post-install smoke check that imports the SDK before accepting a deploy
- Verify Node version against the SDK engines field in CI
- Mark openai as external in SvelteKit/Vite SSR builds so runtime resolution uses node_modules
When it happens
Trigger: First call to endpointOai() (model refresh or first generation) when node cannot resolve/load the openai package: "openai" missing from node_modules, corrupted/partial install, a bundler (Vite/rollup SSR build) failing to resolve or bundle it, or an SDK version whose engine requirements exceed the runtime Node.
Common situations: Fresh clone without npm install/npm ci; a fork that dropped "openai" from package.json; Docker image pruning node_modules incorrectly; pnpm strict hoisting breaking the dynamic import path; Node 16/18 with an ESM-only openai v5+; two conflicting copies of the package after a botched upgrade.
Related errors
- AIDefence failed to load
- module loaded but is missing expected OAuth exports
- pg (node-postgres) package not found. Install it with: npm…
- ruflo auth needs the '@claude-flow/security' package, which…
- "@agntcy/slim-bindings" is installed but does not export…
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/288759c5ff5f3d38.
Report an issue: GitHub.
Appendix: source
Thrown at ruflo/src/ruvocal/src/lib/server/endpoints/openai/endpointOai.ts:73
): Promise<Endpoint> {
const {
baseURL,
apiKey,
completion,
model,
defaultHeaders,
defaultQuery,
multimodal,
extraBody,
useCompletionTokens,
streamingSupported,
} = endpointOAIParametersSchema.parse(input);
let OpenAI;
try {
OpenAI = (await import("openai")).OpenAI;
} catch (e) {
throw new Error("Failed to import OpenAI", { cause: e });
}
// Store router metadata if captured
let routerMetadata: { route?: string; model?: string; provider?: string } = {};
// Custom fetch wrapper to capture response headers for router metadata
const customFetch = async (url: RequestInfo, init?: RequestInit): Promise<Response> => {
const response = await fetch(url, init);
// Capture router headers if present (fallback for non-streaming)
const routeHeader = response.headers.get("X-Router-Route");
const modelHeader = response.headers.get("X-Router-Model");
const providerHeader = response.headers.get("x-inference-provider");
if (routeHeader && modelHeader) {
routerMetadata = {
route: routeHeader,
model: modelHeader,View on GitHub (pinned to fa13ee4ad6)