microsoft/typescript-go · error · ErrClientError

%w: project has no program

Error message

%w: project has no program

What it means

Within a snapshot, the project handle resolved to a live project.Project, but proj.GetProgram() returned nil, so no compiler.Program exists for that project in this snapshot. Checker-backed requests (setupChecker -> sd.getProgram) therefore fail with "api: client error: project has no program". The project exists in the ProjectCollection but a program was never constructed for it - typically because its configuration failed to load or it contains no compilable files.

Source

Thrown at internal/api/session.go:86

// and allow clean teardown when a project is removed.
type projectRegistryData struct {
	typeRegistry   map[TypeID]*checker.Type
	typeRegistryMu sync.RWMutex

	signatureRegistry   map[SignatureID]*checker.Signature
	signatureRegistryMu sync.RWMutex
}

// getProgram looks up a program from a project handle within this snapshot.
func (sd *snapshotData) getProgram(projectHandle ProjectID) (*compiler.Program, error) {
	proj, err := sd.getProject(projectHandle)
	if err != nil {
		return nil, err
	}

	program := proj.GetProgram()
	if program == nil {
		return nil, fmt.Errorf("%w: project has no program", ErrClientError)
	}

	return program, nil
}

// getProject looks up a project from a project handle within this snapshot.
func (sd *snapshotData) getProject(projectHandle ProjectID) (*project.Project, error) {
	projectName := parseProjectHandle(projectHandle)
	proj := sd.snapshot.ProjectCollection.GetProjectByPath(projectName)
	if proj == nil {
		return nil, fmt.Errorf("%w: project %s not found", ErrClientError, projectName)
	}
	return proj, nil
}

// nodeHandleFrom creates an index-based node handle (index.kind.path), building a node index table
// for the file on-demand if needed.
func (sd *snapshotData) nodeHandleFrom(node *ast.Node) NodeHandle {

View on GitHub (pinned to 1bcfa18d79)

Solutions

  1. Re-run updateSnapshot with the project's files opened and confirm it succeeds before issuing checker queries
  2. Validate the project's config first with the parseConfigFile / parseCommandLine requests and fix any reported errors
  3. Use getDefaultProjectForFile for the file you are querying - it returns a project that actually has the file loaded
  4. Confirm the project has source files via getSourceFileNames before assuming a program exists

Example fix

// before
const res = await call("getTypeAtPosition", { snapshot, project, file, position }); // project has no program

// after
const proj = await call("getDefaultProjectForFile", { snapshot, file }); // project that loaded `file`
if (proj) {
  const res = await call("getTypeAtPosition", { snapshot, project: proj, file, position });
}
Defensive patterns

Strategy: validation

Validate before calling

// TS client: confirm the project actually loaded files before checker calls.
const names = await call("getSourceFileNames", { snapshot, project });
if (!names || names.length === 0) {
  throw new Error(`project ${project} has no loaded files - program not built; check its tsconfig`);
}
// only now issue getTypeAtPosition / getSignaturesOfType / ...

Try / catch

try {
  return await call(method, params);
} catch (e) {
  if (String(e).includes("project has no program")) {
    // config likely broken: re-open the project's files via updateSnapshot,
    // validate tsconfig via parseConfigFile, then retry once with the fresh handle
    const fresh = await reopenProject(file);
    return await call(method, { ...params, snapshot: fresh.snapshot, project: fresh.project });
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling type/checker methods (getTypeAtPosition, getSignaturesOfType, getResolvedSignature, ...) with a project handle whose tsconfig failed to parse or whose file list is empty; using a project handle for a config project discovered but not fully loaded in this snapshot; querying before the updateSnapshot that opens the project's files has completed.

Common situations: A broken tsconfig.json (syntax errors, unresolvable extends) so program construction silently yields nil; a project whose include/exclude patterns match zero files; a project reference that was never loaded; racing an editor integration's first checker query against snapshot initialization.

Related errors


AI-assisted analysis of microsoft/typescript-go@1bcfa18d79 (2026-08-16). Data as JSON: /api/errors/e6fd9f4df099d444. Report an issue: GitHub.