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
- Check the installed @earendil-works/pi-ai version and inspect dist/auth/oauth/ to confirm the module file and export name still exist
- Pin or bump the pi-ai dependency to the version the provider adapter was built against (update package.json/lockfile and reinstall)
- Regenerate/update the moduleFile/exportName mapping in packages/providers/src/oauth.ts to match the installed SDK
- 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
- Pin the pi-ai dependency version alongside the adapter code
- Add a startup smoke test that resolves every oauth module/export the adapters need
- Re-run provider auth tests after any dependency bump
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
- Pi OAuth provider '${oauthAuth.name}' produced no apiKey for
- Provider '${provider}' does not support subscription login.
- Vendor '${vendor}' (Pi backend) has no env-based OAuth deliv
- OAuth state mismatch.
- Missing authorization code.
AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01).
Data as JSON: /api/errors/63338372ea0bc11e.
Report an issue: GitHub.