fix(filebrowser): require agent_name when subdomain is false (#877)

## Description

Fixes
[REG-4](https://linear.app/codercom/issue/REG-4/filebrowser-appends-workspace-path-twice-in-url):
the `filebrowser` module opens to a non-existent URL with the workspace
path appended a second time when `subdomain = false` and `agent_name` is
not provided, e.g.:

```
https://<coder-host>/@<owner>/<workspace>/apps/filebrowser/files/@<owner>/<workspace>.<agent>/apps/filebrowser/
```

### Root cause

Coder's frontend always builds path-based app URLs as
`/@<owner>/<workspace>.<agent>/apps/<slug>/` (it always includes
`.<agent_name>`, even for single-agent templates):

https://github.com/coder/coder/blob/main/site/src/modules/apps/apps.ts

```ts
return `${path}/@${workspace.owner_name}/${workspace.name}.${agent.name}/apps/${app.slug}/`;
```

The filebrowser module, however, only includes the agent segment in
`local.server_base_path` (which becomes filebrowser's `--baseURL`) when
the user explicitly passes `agent_name`. The variable description and
the README both said `agent_name` was "only required if the template
uses multiple agents", which is incorrect.

When the URLs disagree, filebrowser's reverse-proxy `stripPrefix` cannot
strip the prefix, the path falls through filebrowser's `/:catchAll(.*)*`
Vue route, and the router redirects to `/files/${catchAll}` — producing
the duplicated path the user reported.

### Fix

- Add a `lifecycle.precondition` on `coder_script.filebrowser` that
fails `terraform apply` with a clear, actionable error when `subdomain =
false` and `agent_name == null`.
- Update the `agent_name` variable description to state it is required
whenever `subdomain` is `false`.
- Update the `README.md` example for the path-based config to call out
the requirement explicitly.
- Bump the module version from `1.1.4` → `1.1.5`.
- Add a TS test covering the new precondition.

This avoids the silent misconfiguration that produces the duplicated
URL, without breaking anyone whose existing template already sets
`agent_name` (or uses `subdomain = true`).

## Type of Change

- [ ] New module
- [ ] New template
- [x] Bug fix
- [ ] Feature/enhancement
- [ ] Documentation
- [ ] Other

## Module Information

**Path:** `registry/coder/modules/filebrowser`  
**New version:** `v1.1.5`  
**Breaking change:** [ ] Yes [x] No

## Testing & Validation

- [x] `bun test main.test.ts` — 8 pass, 0 fail (includes new
precondition test)
- [x] `terraform fmt -recursive`
- [x] `terraform validate`
- [x] `bun x prettier --check`
- [x] Manually verified the precondition fires with a minimal repro and
passes when `agent_name` is supplied or `subdomain = true`.

## Related Issues

- Linear:
[REG-4](https://linear.app/codercom/issue/REG-4/filebrowser-appends-workspace-path-twice-in-url)

---

Created on behalf of @matifali.

Generated with Blink.

Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com>
Co-authored-by: DevCats <christofer@coder.com>
This commit is contained in:
blinkagent[bot]
2026-05-04 15:17:50 -05:00
committed by GitHub
parent 4d96be0de7
commit 4688e4c1a7
3 changed files with 29 additions and 5 deletions
+6 -4
View File
@@ -14,7 +14,7 @@ A file browser for your workspace.
module "filebrowser" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/filebrowser/coder"
version = "1.1.4"
version = "1.1.5"
agent_id = coder_agent.main.id
}
```
@@ -29,7 +29,7 @@ module "filebrowser" {
module "filebrowser" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/filebrowser/coder"
version = "1.1.4"
version = "1.1.5"
agent_id = coder_agent.main.id
folder = "/home/coder/project"
}
@@ -41,7 +41,7 @@ module "filebrowser" {
module "filebrowser" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/filebrowser/coder"
version = "1.1.4"
version = "1.1.5"
agent_id = coder_agent.main.id
database_path = ".config/filebrowser.db"
}
@@ -49,11 +49,13 @@ module "filebrowser" {
### Serve from the same domain (no subdomain)
When `subdomain = false`, you must also set `agent_name` to the name of your `coder_agent` resource. Coder serves path-based apps at `/@<owner>/<workspace>.<agent>/apps/<slug>/`, so the agent name is required to build a base URL that matches the URL the user is actually browsing. If `agent_name` is omitted in this mode, `terraform apply` will fail with an explanatory error.
```tf
module "filebrowser" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/filebrowser/coder"
version = "1.1.4"
version = "1.1.5"
agent_id = coder_agent.main.id
agent_name = "main"
subdomain = false
@@ -102,4 +102,19 @@ describe("filebrowser", async () => {
testBaseLine(output);
}, 15000);
it("fails when subdomain=false and agent_name is not provided", async () => {
let caught: Error | undefined;
try {
await runTerraformApply(import.meta.dir, {
agent_id: "foo",
subdomain: false,
});
} catch (e) {
caught = e as Error;
}
expect(caught).toBeDefined();
expect(caught!.message).toContain("agent_name");
expect(caught!.message).toContain("subdomain");
}, 15000);
});
+8 -1
View File
@@ -20,7 +20,7 @@ data "coder_workspace_owner" "me" {}
variable "agent_name" {
type = string
description = "The name of the coder_agent resource. (Only required if subdomain is false and the template uses multiple agents.)"
description = "The name of the coder_agent resource. Required when `subdomain` is `false` so the path-based base URL matches the URL Coder serves."
default = null
}
@@ -102,6 +102,13 @@ resource "coder_script" "filebrowser" {
SERVER_BASE_PATH : local.server_base_path
})
run_on_start = true
lifecycle {
precondition {
condition = var.subdomain || var.agent_name != null
error_message = "`agent_name` is required when `subdomain` is `false`. Coder always builds path-based app URLs as `/@<owner>/<workspace>.<agent>/apps/<slug>/`, so the filebrowser base URL must include the agent name to match. Set `agent_name = \"<your coder_agent name>\"` (e.g. `\"main\"`)."
}
}
}
resource "coder_app" "filebrowser" {