moeru-ai/airi · error · Error
gameletKit requires a host binding runtime.
Error message
gameletKit requires a host binding runtime.
What it means
In plugin-sdk-tamagotchi's gamelet kit (src/gamelet/index.ts), mount(definition) delegates the actual mounting of a gamelet iframe/widget to gameletRuntime.bindings.bind(...). bindings is a host-provided capability: only the real tamagotchi host process supplies it when it instantiates kit clients for an extension module. If the kit is used in a runtime whose host did not provide a binding runtime (bare SDK host, unit tests, a slim host), mount() refuses to proceed and throws this error rather than returning a handle that could never mount anything.
Solutions
- Run the code inside the real tamagotchi host, which provides gameletRuntime.bindings when creating kit clients.
- If you are building/testing against a custom host, register a bindings implementation (bind({ moduleId, kitId, kitModuleType, config }) returning a mounted binding) in the runtime you pass to kit creation.
- In tests, stub the kit or inject a fake bindings runtime instead of invoking the real mount path.
- Feature-detect before mounting: skip/defer the mount when the host lacks bindings rather than crashing the extension.
Example fix
// before
const gamelets = await module.kits.use(gameletKit)
await gamelets.mount(definition) // throws in tests / slim hosts
// after
const gamelets = await module.kits.use(gameletKit)
if (!gameletRuntimeHasBindings(gamelets)) {
console.warn('gamelet bindings unavailable; skipping mount')
return
}
await gamelets.mount(definition) Defensive patterns
Strategy: validation
Validate before calling
const gamelets = await module.kits.use(gameletKit) // feature-detect host bindings before mounting const canMount = 'mount' in gamelets && hostProvidesBindings() if (canMount) await gamelets.mount(definition)
Type guard
interface HostBindingsRuntime { bindings?: { bind(input: unknown): Promise<unknown> } }
function hasGameletBindings(runtime: HostBindingsRuntime): boolean {
return typeof runtime.bindings?.bind === 'function'
} Try / catch
try {
return await gamelets.mount(definition)
} catch (error) {
if (errorMessageFrom(error).includes('requires a host binding runtime')) {
return undefined // host without UI bindings: skip gamelet registration
}
throw error
} Prevention
- Run gamelet mounting only inside the real tamagotchi host or a host that explicitly documents bindings support.
- In tests, inject a fake bindings runtime instead of exercising the real mount path.
- Feature-detect host capabilities once at module setup and record them, so every later call knows what is available.
When it happens
Trigger: Calling module.kits.use(gameletKit) and then gamelets.mount({...}) inside a unit test, a mock host built with createPluginHost but no binding runtime registered, or a host integration that deliberately omits UI binding capabilities. Also when code accidentally runs the SDK kit outside the tamagotchi application.
Common situations: Extension authors writing vitest suites against their gamelet module with a minimal host; a new host embedding the SDK that has not implemented bindings yet; calling mount during host shutdown when capabilities have been torn down.
Related errors
- gameletKit requires a host gamelet orchestration runtime.
- toolKit requires a host tool registry runtime.
- Tamagotchi extension tool not found
- Tool input schema must be a JSON Schema object or a…
- Cannot declare permissions for unknown plugin
AI-assisted analysis of moeru-ai/airi@677329427f (2026-08-18).
Data as JSON: /api/errors/64caff85c1ae861a.
Report an issue: GitHub.
Appendix: source
Thrown at packages/plugin-sdk-tamagotchi/src/gamelet/index.ts:75
id: 'kit.gamelet',
version: '1.0.0',
allowedExposePolicies: ['local-only', 'remote-observable'],
defaultExposePolicy: 'local-only',
createClient(runtime) {
const gameletRuntime = runtime as GameletKitRuntime
return {
iframe(input) {
return {
mount: 'iframe',
iframe: {
...input,
sandbox: input.sandbox ?? 'allow-scripts allow-same-origin allow-forms allow-popups',
},
}
},
async mount(definition) {
if (!gameletRuntime.bindings) {
throw new Error('gameletKit requires a host binding runtime.')
}
return await gameletRuntime.bindings.bind({
moduleId: definition.bindingId ?? createGameletBindingId(runtime),
kitId: 'kit.gamelet',
kitModuleType: 'gamelet',
config: {
title: definition.title,
widget: definition.ui,
config: {
init: definition.init ?? {},
},
},
})
},
orchestration: gameletRuntime.gamelets,
}
},View on GitHub (pinned to 677329427f)