Skip to content

fix: plugin model without time crashes Model.snapshot and shows false "Session location unavailable" #54943

Open

Description

@laurelhell

Description

A plugin that registers a model without time crashes model loading for the whole directory. The TUI then shows "Session location unavailable — Choose another directory to continue this session", although the directory exists. opencode run fails with:

Error: undefined is not an object (evaluating 'rH.time.released')

The log shows it throws in the sort inside Model.snapshot (called from Model.available). editor.add accepts the incomplete model without validation, so the error only appears later and is misreported as a location problem. Building the model with Model.Info.default(...) avoids it.

Expected: reject or skip the invalid model at editor.add (or log which plugin/model is bad) instead of breaking every session in that directory.

Plugins

A local test plugin (repro below)

OpenCode version

2.0.27

Steps to reproduce

  1. In any project, create .opencode/plugins/bad-model.ts:
import { Plugin, Provider } from "@opencode/plugin";

export default Plugin.define({
  id: "bad-model",
  async setup(ctx) {
    await ctx.provider.transform((editor) => {
      editor.add({
        info: { ...Provider.Info.empty("bad-model"), name: "Bad", activation: "enabled" },
        models: [{
          id: "bad-model.m1", providerID: "bad-model", modelID: "m1", name: "M1",
          capabilities: { tools: true }, limit: { context: 1000, output: 1000 },
        } as any],
      });
    });
  },
});
  1. Run opencode run "hi" in that directory, or open a session there in the TUI.
  2. run fails with the error above; the TUI shows "Session location unavailable".

Operating System

CachyOS Linux (kernel 7.2)

Activity

  1. opencode-agent commented on Oct 12, 2026

    @opencode-agent
    Contributor

    Thanks for the clear repro, I could reproduce this on 2.0.27.

    With your .opencode/plugins/bad-model.ts in a project, opencode run "hi" fails right away with undefined is not an object (evaluating 'rH.time.released'). In the TUI, model loading for the directory breaks: after sending a message, no models are available and the "Connect an integration" dialog opens. The same setup without the plugin works normally. My run only opened a new session, so I didn't see the "Session location unavailable" modal itself; it likely shows when an existing session is reopened, as you describe.

    The TUI problem still happens on the latest dev (a22754f), and the time.released sort in Model.snapshot is unchanged there. The recording, screenshot and script below show the TUI side. Until this is handled, building the model with Model.Info.default(...) as you noted avoids it.

    Related but different causes of the same modal: #49352, #43415.

    recording.mp4

    Screenshot

    Reproduction script (drive.ts)
    import { Effect } from "effect"
    import { OpenCodeDriver } from "opencode-drive"
    
    // Plugin from #54943: registers a model without `time` via editor.add
    const plugin = `import { Plugin, Provider } from "@opencode/plugin";
    export default Plugin.define({
      id: "bad-model",
      async setup(ctx) {
        await ctx.provider.transform((editor) => {
          editor.add({
            info: { ...Provider.Info.empty("bad-model"), name: "Bad", activation: "enabled" },
            models: [{
              id: "bad-model.m1", providerID: "bad-model", modelID: "m1", name: "M1",
              capabilities: { tools: true }, limit: { context: 1000, output: 1000 },
            } as any],
          });
        });
      },
    });
    `
    
    export default OpenCodeDriver.use(
      {
        ...(process.env.OC_DEV ? { opencode: { dev: process.env.OC_DEV } } : {}),
        project: { git: true, files: { ".opencode/plugins/bad-model.ts": plugin } },
        tui: { recording: true },
      },
      ({ ui }) =>
        Effect.gen(function* () {
          yield* ui.screenshot("start")
          yield* Effect.sleep("3 seconds")
          yield* ui.submit("hi")
          yield* ui.waitFor("Session location unavailable", { timeout: 60000 } as any).pipe(
            Effect.catch((e) => Effect.log(`waitFor failed: ${e}`)),
          )
          yield* Effect.sleep("2 seconds")
          yield* ui.screenshot("result")
        }),
    )

    Run it with opencode-drive: opencode-drive run ./drive.ts. It drives opencode from your PATH; set OC_DEV to the path of an OpenCode checkout to run that from source instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions