Crosstalk-Solutions/project-nomad · warning

Service not found

Error message

Service ${params.name} not found

What it means

HTTP 404 from getServiceLogs when no Service row matches the service_name route param. The endpoint is scoped to managed services so arbitrary sibling containers (admin app, database) are not readable by name.

Solutions

  1. List services via the services index endpoint and use the exact service_name
  2. If the service should exist, re-run its installer/registration
  3. Do not attempt to read infra containers (database, admin) through this route
Defensive patterns

Strategy: validation

Validate before calling

const services = await api.listServices()
if (!services.some((s) => s.service_name === name)) return notFound()

Try / catch

try { await getLogs(name) } catch (e: any) { if (e.status === 404) show('Unknown service') else throw e }

Prevention

When it happens

Trigger: GET /services/:name/logs where :name is not a row in the services table — typo'd name, unmanaged container name like the postgres container, or a service not yet registered.

Common situations: Guessing the docker container name instead of the registered service_name; querying logs of infrastructure containers; stale frontend cached name after a service was removed.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of Crosstalk-Solutions/project-nomad@0bd1c6f4f9 (2026-08-27). Data as JSON: /api/errors/0a1142b881812731. Report an issue: GitHub.

Appendix: source

Thrown at admin/app/controllers/system_controller.ts:559

            return response.status(403).send({ success: false, message: 'Only custom apps can be updated this way.' })
        }

        const result = await this.dockerService.recreateCustomAppContainer(payload.service_name, {
            forcePull: true,
        })
        if (result.success) {
            return response.send({ success: true, message: result.message })
        }
        return response.status(400).send({ success: false, message: result.message })
    }

    /** Return the last N lines of a service container's logs. */
    async getServiceLogs({ params, request, response }: HttpContext) {
        // Scope to managed services only — otherwise any sibling container's logs (admin app,
        // database) would be readable by name on this unauthenticated API surface.
        const service = await Service.query().where('service_name', params.name).first()
        if (!service) {
            return response.status(404).send({ success: false, message: `Service ${params.name} not found` })
        }
        const { tail } = await request.validateUsing(serviceLogsValidator)
        const result = await this.dockerService.getContainerLogs(params.name, tail ?? 200)
        if (!result.success) {
            return response.status(404).send({ success: false, message: result.message })
        }
        return response.send({ success: true, logs: result.logs })
    }

    /** Return a one-shot CPU/memory usage snapshot for a running service container. */
    async getServiceStats({ params, response }: HttpContext) {
        // Scope to managed services only (see getServiceLogs).
        const service = await Service.query().where('service_name', params.name).first()
        if (!service) {
            return response.status(404).send({ success: false, message: `Service ${params.name} not found` })
        }
        const result = await this.dockerService.getContainerStats(params.name)
        if (!result.success) {

View on GitHub (pinned to 0bd1c6f4f9)