can1357/oh-my-pi · error

Widget content missing

Error message

Widget content missing

What it means

The extension UI widget hook registered with setHookWidget provided neither static content nor a render function. #createHookWidget expects the widget's `content` to be either an array of renderables or a function (content(this.ctx.ui, theme)); when it is undefined the widget cannot be rendered and this error is thrown. It indicates a malformed extension widget registration rather than a rendering problem.

Source

Thrown at packages/coding-agent/src/modes/controllers/extension-ui-controller.ts:360

	#removeHookWidget(widgets: Map<string, ExtensionUiComponent>, key: string): void {
		const existing = widgets.get(key);
		existing?.dispose?.();
		widgets.delete(key);
	}

	#createHookWidget(content: ExtensionWidgetContent): ExtensionUiComponent {
		if (Array.isArray(content)) {
			const container = new Container();
			for (const line of content.slice(0, MAX_WIDGET_LINES)) {
				container.addChild(new Text(line, 1, 0));
			}
			if (content.length > MAX_WIDGET_LINES) {
				container.addChild(new Text(theme.fg("muted", "... (widget truncated)"), 1, 0));
			}
			return container;
		}
		if (content === undefined) {
			throw new Error("Widget content missing");
		}
		return content(this.ctx.ui, theme);
	}

	#rebuildHookWidgets(): void {
		this.#renderHookWidgetContainer(this.ctx.hookWidgetContainerAbove, this.#hookWidgetsAbove, true, true);
		this.#renderHookWidgetContainer(this.ctx.hookWidgetContainerBelow, this.#hookWidgetsBelow, false, false);
		this.ctx.ui.requestRender();
	}

	#renderHookWidgetContainer(
		container: Container,
		widgets: Map<string, ExtensionUiComponent>,
		spacerWhenEmpty: boolean,
		leadingSpacer: boolean,
	): void {
		container.clear();

View on GitHub (pinned to 9690622007)

Solutions

  1. Fix the extension to always supply `content` — either a renderable array or a `(ui, theme) => ...` function
  2. In the extension, fall back to placeholder content (e.g. an empty container) when data is unavailable instead of undefined
  3. Disable or update the offending extension to a version compatible with the current widget API
  4. Guard the extension's widget registration with a check that content is defined before calling setHookWidget

Example fix

// before
widget.setContent(data?.renderable); // may be undefined
// after
widget.setContent(data?.renderable ?? [new Text(theme.fg('muted', 'no data'), 1, 0)]);
Defensive patterns

Strategy: validation

Validate before calling

// Before registering an extension widget
if (widget.content === undefined) {
  throw new Error('Extension widget must define content (renderables or render function)');
}
extensionUi.setHookWidget(widget);

Type guard

function hasWidgetContent(w: { content?: unknown }): w is { content: NonNullable<unknown> } {
  return w.content !== undefined;
}

Try / catch

try {
  extensionUi.setHookWidget(widget);
} catch (err) {
  if (err instanceof Error && err.message === 'Widget content missing') {
    logger.warn('Extension widget rejected: no content', { id: widget.id });
  }
}

Prevention

When it happens

Trigger: An extension/hook calls setHookWidget with a widget object whose `content` field is undefined — e.g. the hook computed content conditionally and returned undefined, or passed an object with a misspelled/missing content key.

Common situations: A third-party extension built against an older widget API where content was optional; an extension that returns undefined from an async lookup (e.g. failed fetch for widget data) and passes it straight through; a typo like `{ ctx }` instead of `{ content }`.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/ac75f5768157aa64. Report an issue: GitHub.