abhigyanpatwari/GitNexus · error

Local embeddings are unavailable after the sidecar aborted

Error message

Local embeddings are unavailable after the sidecar aborted

What it means

This error is thrown by the internal spawnAndInit step of the embedding sidecar client. The sidecar child process previously died in a way indicating a native abort (SIGSEGV/SIGABRT/SIGBUS/SIGILL) or had already exhausted the single recreate attempt (MAX_RECREATES = 1), so the client latches `localUnavailable` and permanently refuses to spawn a new sidecar for this process lifetime. It prevents repeated crashes from an ONNX runtime or native binary that is fundamentally broken in this environment.

Solutions

  1. Restart the GitNexus process — the `localUnavailable` latch is in-memory only, so a fresh process clears it (after fixing the underlying crash cause).
  2. Check sidecar stderr in debug logs for the native crash signature; reinstall or update onnxruntime-node / the model runtime so the native binary matches the platform.
  3. Use a remote embedding provider instead of local embeddings (e.g. configure GITNEXUS_EMBEDDING_URL or an API-based provider) to bypass the sidecar entirely.
  4. If the crash came from the device choice, retry with a different device (e.g. force CPU instead of GPU) once the process has been restarted.
  5. Free memory or raise container limits if the abort correlates with model loading OOM.

Example fix

// before: retrying embed calls in a process where the sidecar already aborted
const vectors = await sidecarEmbedBatch(texts); // throws forever
// after: check device availability first and fall back to a remote provider
if (getSidecarDevice() === null) {
  const vectors = await remoteEmbedBatch(texts);
} else {
  const vectors = await sidecarEmbedBatch(texts);
}
Defensive patterns

Strategy: fallback

Validate before calling

// check local runtime availability before requesting local embeddings
import { getLocalEmbeddingRuntimeBlocker } from './runtime-support.js';
const blocker = getLocalEmbeddingRuntimeBlocker();
if (blocker) useRemoteEmbeddings();

Type guard

// narrow to a sidecar-capable state
const canEmbedLocally = (): boolean => getSidecarDevice() !== null;

Try / catch

try {
  await sidecarInit();
} catch (err) {
  if (String(err.message).includes('sidecar aborted')) {
    logger.error('Local embeddings permanently unavailable; switching to remote provider');
    enableRemoteEmbeddings();
  } else {
    throw err;
  }
}

Prevention

When it happens

Trigger: Calling ensureEmbeddingSidecar (directly or via sidecarEmbedBatch) after a prior sidecar died with a native abort signal, or after the sidecar died once, was recreated once, and died again — markUnavailableIfBudgetSpent() sets localUnavailable and line 309 throws on the next spawn attempt.

Common situations: Broken or mismatched onnxruntime-node native binaries; CPU without required instruction sets (e.g. AVX) for the model runtime; sidecar killed by the OS (OOM/segfault) during model download or inference; GPU/CUDA library conflicts when forceDevice was requested.

Related errors


AI-assisted analysis of abhigyanpatwari/GitNexus@ac9a4e9abd (2026-09-15). Data as JSON: /api/errors/56b5683517e890bd. Report an issue: GitHub.

Appendix: source

Thrown at gitnexus/src/core/embeddings/embedding-sidecar-client.ts:309

  onProgress?: (progress: ModelProgress) => void;
  embeddingConfig?: Partial<EmbeddingConfig>;
  forceDevice?: EmbeddingSidecarDevice;
  signal?: AbortSignal;
};

const markUnavailableIfBudgetSpent = (): void => {
  if (deathSeen && recreatesUsed >= MAX_RECREATES) {
    localUnavailable = true;
  }
};

const spawnAndInit = async (options?: EnsureSidecarOptions): Promise<void> => {
  const runtimeBlocker = getLocalEmbeddingRuntimeBlocker();
  if (runtimeBlocker) {
    throw new Error(runtimeBlocker);
  }
  markUnavailableIfBudgetSpent();
  if (localUnavailable) throw localUnavailableError();

  if (deathSeen) {
    recreatesUsed += 1;
    deathSeen = false;
  }

  const persisted = {
    embeddingConfig: options?.embeddingConfig ?? lastInitOptions?.embeddingConfig,
    forceDevice: options?.forceDevice ?? lastInitOptions?.forceDevice,
  };

  child = spawnSidecar();
  attachChild(child);
  progressSink = options?.onProgress;
  try {
    const response = await request(
      {
        type: 'init',

View on GitHub (pinned to ac9a4e9abd)