Repository navigation
Conversation
A request that needs the model catalog waits for the location's plugins to activate, and gives up after five seconds with `ServiceUnavailableError: Location plugins did not finish activating`. Five seconds is a fixed cost that has to cover the whole activation of a cold location: building the location, resolving its plugin sources, loading the plugin modules, and running their setup. On a loaded machine that is not always enough. When it is not, the request fails even though activation was still making progress, and the client retries against the same location. The budget is now read from OPENCODE_PLUGIN_ACTIVATION_TIMEOUT, so a slow machine can give its plugins the time they need. The default stays at five seconds, so nothing changes for anyone who does not set it, and an unreadable value keeps the default rather than failing every request. The environment variable is read per request, so a server that inherits it from its parent picks it up without a restart.
|
This PR doesn't fully meet our contributing guidelines and PR template. What needs to be fixed:
Please edit this PR description to address the above within 72 hours, or it will be automatically closed. If you believe this was flagged incorrectly, please let a maintainer know. |
There was a problem hiding this comment.
The variable works as described when calling awaitPlugins directly: with it set, slow activation either gets more time or fails sooner. I checked this with the added tests (5 pass), a clean bun run typecheck in packages/server, and a probe of how activationBudget() parses a range of values. I did not run a full server against a slow plugin.
Public API: adds the environment variable OPENCODE_PLUGIN_ACTIVATION_TIMEOUT and documents it in the CLI docs. It is backwards compatible because the default stays at 5 seconds. No change to the HTTP API, the SDK or config.
Concerns:
- Wrong formats are silently ignored.
30000,30and30sall quietly fall back to 5s, so a user who sets the variable can easily get no effect with no feedback. The docs row doesn't say which format is expected. - Zero and negative values are accepted.
0 millisand-5 secondsmake every request that waits for plugins fail immediately with a 503.
Details are in the inline comments. Small point: the description says reading the variable per request means a running server picks up a new value without a restart. A process's environment doesn't change after it starts, so that benefit doesn't exist. It doesn't block anything, but the per-request read only helps the tests.
| const configured = process.env.OPENCODE_PLUGIN_ACTIVATION_TIMEOUT?.trim() | ||
| if (!configured) return defaultActivationBudget | ||
| try { | ||
| return Duration.fromInputUnsafe(configured as Duration.Input) |
There was a problem hiding this comment.
fromInputUnsafe on a raw string, with a catch that hides failures, causes two problems:
- Wrong formats do nothing, silently. Common forms like
30000,30and30s(and1e9 seconds) all fall back to 5s, so a user who sets the variable gets no change and no warning. - Zero and negative values are accepted.
0 millisgives 0 and-5 secondsgives -5s, which turns everyawaitPluginscall into an immediate 503.
A plain positive number of milliseconds, like the existing OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS, would be harder to get wrong. Whatever format you keep, please reject values that aren't positive, and log a warning when a value is ignored instead of hiding it.
| | `OPENCODE_TUI_CONFIG` | string | Path to TUI config file | | ||
| | `OPENCODE_CONFIG_DIR` | string | Path to config directory | | ||
| | `OPENCODE_CONFIG_CONTENT` | string | Inline json config content | | ||
| | `OPENCODE_PLUGIN_ACTIVATION_TIMEOUT` | string | How long location plugins may take to activate | |
There was a problem hiding this comment.
Please state the accepted format and the default here, for example "Plugin activation timeout, e.g. 30 seconds (default 5 seconds)". Without it, users will likely try 30000 or 30s, and both are currently ignored.
|
This pull request has been automatically closed because it was not updated to meet our contributing guidelines within the 72-hour window. Feel free to open a new pull request that follows our guidelines. |
Problem
A request that needs the model catalog waits for the location's plugins to activate, and gives up after five seconds:
Five seconds is a fixed cost that has to cover the whole activation of a cold location — building the location, resolving its plugin sources, loading the plugin modules, and running their setup. On a loaded machine that is not always enough, and the failure mode is worse than a slow response: the request fails while activation is still making progress, and the client then retries against the same location.
Measured on a busy machine, one location was still activating seven seconds after it started warming up, while every request that needed its catalog had already been rejected at five.
Change
The budget is now read from
OPENCODE_PLUGIN_ACTIVATION_TIMEOUT, so a slow machine can give its plugins the time they need:packages/web/src/content/docs/cli.mdxdocuments the variable.Verification
bun test test/location-plugins.test.tsinpackages/server: 5 pass, 0 failactivationBudgetdoes not exist; the behavioural assertions fail with the hard-coded budget in placebun run typecheckinpackages/server: cleanbunx oxlinton both changed files: 0 warnings, 0 errorsbun run check: greenNotes
This does not change what happens when a location's plugins genuinely fail — those still surface as a failed plugin in the inventory, and a request that cannot be served still gets a 503. It only gives slow-but-progressing activation the room it needs, which is the case the fixed five-second wall turned into a failure.
The client side already retries a failed sync, so raising the budget is a way to avoid the retry storm rather than a replacement for it.
Added by the opencode bot (AI-generated).
Related: #57204, #55937
Public API: adds the OPENCODE_PLUGIN_ACTIVATION_TIMEOUT environment variable (backwards compatible, default unchanged at 5s)