abhigyanpatwari/GitNexus · error · Error

No suitable device found for embedding model

Error message

No suitable device found for embedding model

What it means

Thrown by initEmbedder() after the device-probe for-loop completes without returning. Logically this is a defensive safety net: when devicesToTry is non-empty, the last device's error is already rethrown at line 247, and network errors rethrow at line 239 — so reaching this line means the loop body neither returned nor threw on any device, which should not happen with the current device list construction. It exists to convert a silent fall-through into an explicit failure rather than returning undefined.

Source

Thrown at gitnexus/src/core/embeddings/embedder.ts:252

              ? `The configured endpoint (${process.env.HF_ENDPOINT}) may be unreachable.`
              : `huggingface.co may be unreachable from your network.\n` +
                `  Set HF_ENDPOINT to a mirror and retry:\n` +
                `    HF_ENDPOINT=https://hf-mirror.com npx gitnexus analyze --embeddings\n` +
                `    (Windows: set HF_ENDPOINT=https://hf-mirror.com && npx gitnexus analyze --embeddings)`;
            throw new Error(`Failed to download embedding model: ${errMsg}\n  ${endpointHint}`);
          }
          if (isDev && (device === 'cuda' || device === 'dml')) {
            const gpuType = device === 'dml' ? 'DirectML' : 'CUDA';
            logger.info(`⚠️  ${gpuType} not available, falling back to CPU...`);
          }
          // Continue to next device in list
          if (device === devicesToTry[devicesToTry.length - 1]) {
            throw deviceError; // Last device failed, propagate error
          }
        }
      }

      throw new Error('No suitable device found for embedding model');
    } catch (error) {
      isInitializing = false;
      initPromise = null;
      embedderInstance = null;
      throw error;
    } finally {
      isInitializing = false;
    }
  })();

  return initPromise;
};

/**
 * Check if the embedder is initialized and ready
 */
export const isEmbedderReady = (): boolean => {
  return isHttpMode() || embedderInstance !== null;

View on GitHub (pinned to d540b00184)

Solutions

  1. Retry the analyze — if transient, the device probe may succeed next time.
  2. Set GITNEXUS_EMBEDDING_DEVICE=cpu explicitly to collapse the device list to a single deterministic attempt.
  3. If it reproduces, file a GitNexus issue with the GitNexus version, OS/arch, and device config — this path is not expected to be reachable.
  4. Switch to HTTP mode (GITNEXUS_EMBEDDING_URL) to bypass the local device probe entirely.

Example fix

# before — auto device selection reaches an unexpected fall-through
$ npx gitnexus analyze --embeddings
# after — pin to cpu to make the device list deterministic
$ GITNEXUS_EMBEDDING_DEVICE=cpu npx gitnexus analyze --embeddings
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await initEmbedder();
} catch (err) {
  if (err instanceof Error && err.message === 'No suitable device found for embedding model') {
    // Pin a device and retry; if it reproduces, report it — this path is defensive.
    process.env.GITNEXUS_EMBEDDING_DEVICE = 'cpu';
    await initEmbedder();
  } else throw err;
}

Prevention

When it happens

Trigger: Effectively unreachable under normal control flow — the loop always either returns embedderInstance on success or throws (network error, or last-device error). Could surface only if a future change to devicesToTry produced an empty list, or if a device attempt resolved without setting embedderInstance and without throwing.

Common situations: Not expected in practice; if observed, indicates a logic regression in device-list construction or a transformers.js pipeline() that returned a falsy value without throwing.

Related errors


AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12). Data as JSON: /api/errors/a0be2c45f3191287. Report an issue: GitHub.