coleam00/Archon · error

Pi SDK module '${moduleFile}' has no export '${exportName}'.

Error message

Pi SDK module '${moduleFile}' has no export '${exportName}'.

What it means

loadOAuthAuth resolves a deep module ('dist/auth/oauth/<moduleFile>') inside the installed @earendil-works/pi-ai SDK and reads the named export, which must be an OAuthAuth implementation. The throw means the module loaded but did not export the expected symbol — almost always because the installed SDK version has a different internal auth module layout or export name than the provider adapter expects. The cache is only populated after a successful lookup, so the failure repeats on every call.

Source

Thrown at packages/providers/src/oauth.ts:64

const oauthAuthCache = new Map<string, OAuthAuth>();

async function loadOAuthAuth(moduleFile: string, exportName: string): Promise<OAuthAuth> {
  const cached = oauthAuthCache.get(moduleFile);
  if (cached) return cached;
  const { createRequire } = await import('node:module');
  const { fileURLToPath } = await import('node:url');
  // Called through the module object: node:path types dirname/join as
  // PlatformPath methods, so destructuring them trips eslint unbound-method.
  const path = await import('node:path');
  // fileURLToPath returns backslash-separated paths on Windows — build the
  // deep path with node:path, never string concatenation on '/'.
  const sdkPkgPath = fileURLToPath(import.meta.resolve('@earendil-works/pi-ai/package.json'));
  const deepPath = path.join(path.dirname(sdkPkgPath), 'dist', 'auth', 'oauth', moduleFile);
  const require = createRequire(import.meta.url);
  const mod = require(deepPath) as Record<string, OAuthAuth>;
  const oauthAuth = mod[exportName];
  if (!oauthAuth) {
    throw new Error(`Pi SDK module '${moduleFile}' has no export '${exportName}'.`);
  }
  oauthAuthCache.set(moduleFile, oauthAuth);
  return oauthAuth;
}

/* ─── Legacy surface preserved for `@archon/core` consumers ───────────────── */

/** Subset of the pre-0.84 callback-driven login surface the bridge relies on. */
export interface OAuthLoginCallbacks {
  onAuth(info: { url: string; instructions?: string }): void;
  onDeviceCode(info: { userCode: string; verificationUri: string }): void;
  onManualCodeInput?(): Promise<string>;
  onPrompt(prompt: unknown): Promise<string>;
  onSelect(prompt: {
    options: readonly { id: string; label?: string }[];
  }): Promise<string | undefined>;
  onProgress?(message: string): void;
  signal?: AbortSignal;

View on GitHub (pinned to 0773b97458)

Solutions

  1. Check the installed @earendil-works/pi-ai version and inspect dist/auth/oauth/ to confirm the module file and export name still exist
  2. Pin or bump the pi-ai dependency to the version the provider adapter was built against (update package.json/lockfile and reinstall)
  3. Regenerate/update the moduleFile/exportName mapping in packages/providers/src/oauth.ts to match the installed SDK
  4. Clear node_modules and reinstall to rule out a corrupted or duplicated hoisted copy

Example fix

// before (SDK renamed the export)
loadOAuthAuth('anthropic.js', 'anthropicOAuth');
// after (match the installed SDK's actual export)
loadOAuthAuth('anthropic.js', 'anthropic');
Defensive patterns

Strategy: validation

Validate before calling

import { createRequire } from 'node:module';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const sdkPkgPath = fileURLToPath(import.meta.resolve('@earendil-works/pi-ai/package.json'));
const deepPath = path.join(path.dirname(sdkPkgPath), 'dist', 'auth', 'oauth', moduleFile);
const mod = createRequire(import.meta.url)(deepPath);
if (typeof mod?.[exportName] !== 'function') {
  throw new Error(`pi-ai ${moduleFile} missing export ${exportName}; check installed version`);
}

Type guard

function hasOAuthExport(mod: Record<string, unknown>, name: string): mod is Record<string, OAuthAuth> {
  return typeof mod[name] === 'function';
}

Try / catch

try {
  oauthAuth = loadOAuthAuth(moduleFile, exportName);
} catch (err) {
  console.error(`SDK/adapter mismatch for ${moduleFile}.${exportName}; verify pi-ai version`, err);
  throw err;
}

Prevention

When it happens

Trigger: anthropicOAuthProvider or githubCopilotOAuthProvider calls loadOAuthAuth(moduleFile, exportName) and require(deepPath) returns an object without the exportName key (e.g. SDK upgraded/renamed its 'dist/auth/oauth/*.js' files, or a wrong/partial install resolves a stale copy).

Common situations: Pi SDK version drift after a dependency bump; a lockfile pinning an older/newer pi-ai whose internal oauth module files moved; monorepo hoisting resolving a different pi-ai copy than intended; upstream SDK refactors renaming exports without a semver major.

Related errors


AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01). Data as JSON: /api/errors/63338372ea0bc11e. Report an issue: GitHub.