Groundfloor Docs

Troubleshooting

Common issues when developing and deploying federated Shell apps.

Audience: Shell and federated app developers

Symptoms grouped by layer. Start with bootstrap (public, no auth), then auth, then pillar APIs.


Shell bootstrap

Bootstrap returns 404

CauseFix
Wrong slugMatch Portal app detail slug exactly
Wrong workspace_idCopy UUID from Portal workspace URL
App archivedRe-register or un-archive in Portal
Typo in URLPath is /v1/public/workspaces/{uuid}/apps/by-slug?slug=

Bootstrap returns 400

App exists but app_kind is not shell_federated. Register a new Shell app or use Coderunner docs for other kinds.

manifest.remoteUrl is empty

CauseFix
Never publishedPortal → app → Publish build
Publish failedCheck finalize step; confirm MinIO/object store up
Dev without publishSet SHELL_REMOTE_DEV_URL on Shell host

remoteEntry.js returns 404 or CORS error

CauseFix
Stale URL after re-publishRe-fetch bootstrap (cache TTL)
Object store downdocker compose -f deploy/docker-compose.phase2-deps.yml --profile minio up -d
Wrong public base URLCheck OBJECT_STORE_PUBLIC_BASE_URL in Control Plane .env
Browser blockedMinIO CORS for Shell origin

Module Federation load failure

CauseFix
appId mismatchRemote scope must equal manifest.appId
Wrong remote URL formatURL must point at remoteEntry.js file
Shared dependency version skewAlign React/webpack versions with Shell host

Authentication (Keycloak)

401 Invalid token / issuer mismatch

CauseFix
KEYCLOAK_ISSUER wrong on APIMatch token iss claim (no trailing slash)
Expired tokenCall keycloak.updateToken(30) before API calls
Wrong realm/clientAlign NEXT_PUBLIC_KEYCLOAK_* with Portal

401 Token audience mismatch

API KEYCLOAK_AUDIENCE must include your browser client's id. Token often has aud: "account" — check azp claim and add that client id to the comma-separated list.

403 Forbidden

User is authenticated but lacks SpiceDB permission on the workspace.

NeedPermission
Read vault/files/secrets/modelsread
Upload files, write vaultwrite
Mint LLM virtual keyadminister
Create/drop collectionsddl

Add membership in Portal → workspace → members.

CORS error from browser

Add Shell origin to Control Plane CORS_ORIGINS in .env:

["http://localhost:3000","http://localhost:3001"]

Restart API after change.


Data Vault

503 No Dataplane service API key

Workspace provisioning did not store DATAPLANE_SERVICE_API_KEY in Infisical.

  1. Confirm workspace status is active
  2. Re-run provisioning or scripts/backfill_dataplane_workspace_key.py
  3. Bring up Infisical — Phase 2 deps runbook

502 Dataplane auth failed (401)

CauseFix
Invalid workspace keyRe-provision workspace
Dataplane not runningStart groundfloor-dataplane-oss stack
Wrong DATAPLANE_URLDefault http://localhost:8080

502 malformed response / timeout

Dataplane reachable but collection/engine error. Check Dataplane logs; verify collection name in query path.

404 Collection not found

Collection not created in this workspace tenant. Use Portal Data Vault UI or DDL API — 04-data-vault.md.

Empty query results

Filter too restrictive; wrong collection; or no data. Try query without filter first.


Files

409 on finalize — bucket object missing

PUT to presigned URL failed or was skipped.

  1. Confirm PUT returned 200
  2. Check URL not expired (1h default)
  3. Verify Content-Type header matches init request

409 on download — file not active

Still pending (finalize not called) or deleted.

Browser upload fails silently

CORS on MinIO; ad blocker; or mixed content (HTTPS Shell → HTTP MinIO in dev).


Secrets

502 Bad gateway

Infisical not running or machine identity not configured in Control Plane .env.

404 on reveal

Key does not exist — list keys first with GET …/secrets.


LLM Gateway

502 on mint virtual key

LiteLLM not running:

docker compose -f deploy/docker-compose.phase2-deps.yml --profile litellm up -d
curl http://localhost:4000/health/liveness

LiteLLM chat completion fails

CauseFix
No provider keysAdd OPENAI_API_KEY (or similar) to workspace Secrets
Invalid virtual keyRe-mint and update LITELLM_API_KEY secret
Wrong model idUse gf-chat-default etc. from GET …/llm/models

Publish (app releases)

Zip publish — remote not found

remoteEntry.js must be at zip root, not nested in a folder.

App status stuck registered

Normal until first successful publish → transitions to active.


Debugging commands

# API health
curl -s http://localhost:8088/health | jq .

# Bootstrap
curl -s "http://localhost:8088/v1/public/workspaces/${WORKSPACE_ID}/apps/by-slug?slug=${SLUG}" | jq .

# Remote entry HEAD
curl -sI "$(curl -s ... | jq -r .manifest.remoteUrl)" | head -5

# Vault collections (needs TOKEN)
curl -s "http://localhost:8088/v1/workspaces/${WORKSPACE_ID}/vault/collections" \
  -H "Authorization: Bearer ${TOKEN}" | jq .

More recipes: 11-local-dev-recipes.md.


Get help

ResourceLocation
Portal bootstrap URLsApp detail → Shell bootstrap card
OpenAPI try-it{CONTROLPLANE_URL}/docs
Phase 1 plandocs/plans/federated-shell-apps-phase1.md
Control Plane pillar statusPLAN.md

On this page