# Retrieve build logs

> Retrieve build logs - Retrieve the log output of an image build and use it to diagnose failures.

This Markdown file sits beside the HTML page at the same path (with a `.md` suffix). It summarizes the topic and lists links for tools and LLM context.

Companion generated at `2026-09-30T19:40:40.961706+00:00` (UTC).

## Primary page

- [Retrieve build logs](https://docs.datarobot.com/en/docs/workload-api/build-artifacts/build-from-code/build-logs.html.md): Full documentation for this topic (Markdown sidecar).

## Sections on this page

- [Retrieve a build log](https://docs.datarobot.com/en/docs/workload-api/build-artifacts/build-from-code/build-logs.html.md#retrieve-a-build-log): In-page section heading.
- [Query parameters](https://docs.datarobot.com/en/docs/workload-api/build-artifacts/build-from-code/build-logs.html.md#query-parameters): In-page section heading.
- [When logs are not available](https://docs.datarobot.com/en/docs/workload-api/build-artifacts/build-from-code/build-logs.html.md#logs-not-available): In-page section heading.
- [Diagnose a failed build](https://docs.datarobot.com/en/docs/workload-api/build-artifacts/build-from-code/build-logs.html.md#diagnose-a-failed-build): In-page section heading.
- [Next steps](https://docs.datarobot.com/en/docs/workload-api/build-artifacts/build-from-code/build-logs.html.md#next-steps): In-page section heading.

## Related documentation

- [Workload API](https://docs.datarobot.com/en/docs/workload-api/index.html.md): Linked from this page.
- [Build artifacts](https://docs.datarobot.com/en/docs/workload-api/build-artifacts/index.html.md): Linked from this page.
- [Build artifacts from source code](https://docs.datarobot.com/en/docs/workload-api/build-artifacts/build-from-code/index.html.md): Linked from this page.
- [Monitor telemetry and health](https://docs.datarobot.com/en/docs/workload-api/monitor-workloads/index.html.md): Linked from this page.
- [error reference](https://docs.datarobot.com/en/docs/workload-api/build-artifacts/build-from-code/build-operations.html.md#error-reference): Linked from this page.
- [Monitoring concepts](https://docs.datarobot.com/en/docs/workload-api/monitor-workloads/monitoring-concepts.html.md#retention-summary): Linked from this page.
- [Known limitations of custom base images](https://docs.datarobot.com/en/docs/workload-api/build-artifacts/build-from-code/build-from-code.html.md#base-image-limitations): Linked from this page.
- [Container requirements](https://docs.datarobot.com/en/docs/workload-api/build-artifacts/artifacts-concepts.html.md#container-requirements): Linked from this page.
- [Health and readiness](https://docs.datarobot.com/en/docs/workload-api/monitor-workloads/health-readiness.html.md): Linked from this page.

## Documentation content

> [!NOTE] Premium feature
> The Workload API is a premium feature. Contact your DataRobot representative or administrator for information on enabling the feature.

Every image build produces builder output—base image pulls, dependency resolution, each Dockerfile step, and the error that stopped it if it failed. Build logs are how you find out why a build reported `FAILED`, and how you watch a long build make progress.

The builder exports its output as OpenTelemetry logs, and you read them from the platform observability surface, keyed by artifact:

```
GET /api/v2/otel/artifact/{artifactId}/logs/
```

Note the singular `artifact` in the path—that segment is the OTel entity type, not the Workload API's `/artifacts` collection. The Workload API itself does not expose or proxy `/otel/*` routes.

Build logs cover the build. For logs from the container once it is running, see [Monitor telemetry and health](https://docs.datarobot.com/en/docs/workload-api/monitor-workloads/index.html.md).

## Retrieve a build log

Retrieve build output directly through the REST API, or with the CLI when the project directory is already linked.

**cURL:**
```
# Every build the artifact has ever run
curl -s "${DATAROBOT_ENDPOINT}/otel/artifact/${ARTIFACT_ID}/logs/" \
  -H "Authorization: Bearer ${DATAROBOT_API_TOKEN}"

# One build, filtered by its Workload API build ID
curl -s "${DATAROBOT_ENDPOINT}/otel/artifact/${ARTIFACT_ID}/logs/?searchKeys=external_build_id&searchValues=${BUILD_ID}" \
  -H "Authorization: Bearer ${DATAROBOT_API_TOKEN}"
```

**CLI:**
```
dr artifact build logs ${ARTIFACT_ID} ${BUILD_ID}

# Show warnings and errors only
dr artifact build logs ${ARTIFACT_ID} ${BUILD_ID} --level warn
```

Inside a directory linked with `dr artifact code init`, the artifact ID can be omitted.

The CLI prints one structured record per line and hides anything below `info`. Lower `--level` to `debug` to see everything.


The stream is scoped to the artifact, so without a filter it contains every build the artifact has run.`external_build_id` narrows it to one build:

| Attribute | Value |
| --- | --- |
| Service name | artifact-<artifactId>—identifies the stream itself |
| external_build_id | The Workload API build ID, stamped on every record of that build |
| log_source | build_output for the builder's own output |

The response is JSON, one object per log record:

```
{
  "count": 100,
  "next": "https://app.datarobot.com/api/v2/otel/artifact/68f0.../logs/?offset=100&limit=100",
  "previous": null,
  "data": [
    {
      "timestamp": "2026-08-18 09:14:22.481000+00:00",
      "level": "INFO",
      "message": "Step 6/12 : RUN uv sync --frozen"
    }
  ]
}
```

`stacktrace`, `spanId`, and `traceId` appear on records that carry them.`count` is the size of the page you were served, not the total number of records—page through with `next` until it is `null`.

### Query parameters

The following table describes each supported parameter.

| Parameter | Description |
| --- | --- |
| searchKeys, searchValues | Attribute filter, paired positionally. Both must be supplied and must be the same length—supplying one alone returns 400. Up to 10 pairs, each value at most 100 characters. |
| level | Minimum level to return: debug, info, warn, warning, error, or critical. Defaults to debug. Lowercase only—level=INFO returns 400. |
| includes, excludes | Substrings a record must contain, or must not contain. Up to 10 each. |
| startTime, endTime | RFC 3339 bounds. startTime must be earlier than endTime. |
| offset, limit | Pagination. offset defaults to 0; limit defaults to 100 and caps at 1000. next and previous in the response carry ready-made URLs. |
| spanId, traceId | Restrict to records correlated with a specific OTel span or trace. |

> [!NOTE] Query parameters are camelCase; attribute names are not
> Like the rest of the public API, the parameters themselves are camelCase ( `searchKeys`), and `search_keys` returns `400`. The values you filter on are raw OTel attribute names, which are snake_case— `external_build_id`, `log_source`.

> [!NOTE] Logs are a snapshot, not a stream
> The endpoint returns what has been exported at the moment you call it. There is no `follow` or websocket variant. To watch a build in progress, call it again:
> 
> ```
> while true; do
>   clear
>   curl -s "${DATAROBOT_ENDPOINT}/otel/artifact/${ARTIFACT_ID}/logs/?searchKeys=external_build_id&searchValues=${BUILD_ID}" \
>     -H "Authorization: Bearer ${DATAROBOT_API_TOKEN}" \
>     | jq -r '.data[] | "\(.timestamp) \(.level) \(.message)"'
>   sleep 10
> done
> ```

## When logs are not available

An artifact with no matching records returns `200` with an empty `data` array rather than an error, so an empty result is not a failure:

| Empty result | What it means | What to do |
| --- | --- | --- |
| The build is PENDING or IN_PROGRESS | Export lags the builder by a few seconds; early records may not have landed yet. | Wait a few seconds and call again. |
| The build ended FAILED or CANCELLED immediately | The build request was rejected before the builder started, so there is no builder output at all. | Check the artifact's imageBuildConfig and codeRef, then retrigger. The error reference covers the common causes. |
| An older build returns nothing | OTel retention is configured per organization and the records have aged out. See Monitoring concepts. | Retrieve logs while a build is recent, before they age out. |
| external_build_id matches nothing but the unfiltered stream has records | The build ID is wrong, or belongs to a different artifact. | Confirm it with GET /artifacts/{artifact_id}/builds. |

Error responses:

| HTTP | Meaning |
| --- | --- |
| 400 | An invalid query parameter—an uppercase level, searchKeys without searchValues, or mismatched list lengths. The message names the parameter. |
| 404 | The artifact does not exist, or you lack a role on it. |

> [!NOTE] Availability
> Build log export depends on the platform's OpenTelemetry observability stack. On installations where it is not present—including air-gapped installations—builds run normally, but the endpoint returns no records.

## Diagnose a failed build

Read the log from the bottom: the last builder step before the error is nearly always the cause.

| In the log | Cause | Fix |
| --- | --- | --- |
| unknown instruction: ... | A syntax error in your Dockerfile. | Correct the Dockerfile, re-sync, and rebuild. |
| pull access denied, or a failure resolving the FROM image | The base image does not exist or is not reachable from the build environment. | Check the image reference. For a generated Dockerfile, check that the execution environment version resolves to a real image. |
| A dependency resolver error naming a package or version | A dependency cannot be satisfied—a typo, a yanked release, or an incompatible version pin. | Fix the dependency, regenerate the lockfile (uv lock or npm install), re-sync, and rebuild. |
| A compiler error (gcc, error: command ... failed) while installing a dependency | The package builds from source and the base image has no C/C++ toolchain. | Use a DataRobot-published execution environment, or a base image that includes build tools. See Known limitations of custom base images. |
| failed to execute build action, or a step failing without further detail | A RUN step in your Dockerfile exited non-zero. | Reproduce that step locally against the same base image. |
| The build fails with no builder output at all | The build request was rejected before the builder started. | See the error reference. |

If a build succeeds but the container does not start, the problem is runtime rather than build: check the entrypoint, the port, and the readiness probe against [Container requirements](https://docs.datarobot.com/en/docs/workload-api/build-artifacts/artifacts-concepts.html.md#container-requirements), then use [Health and readiness](https://docs.datarobot.com/en/docs/workload-api/monitor-workloads/health-readiness.html.md).

## Next steps

Reading build output is one part of managing the build lifecycle; the following resources cover the surrounding build operations and Dockerfile configuration.

| Goal | Go here |
| --- | --- |
| Retrigger, cancel, or track a build | Trigger and manage builds |
| Change the base image or Dockerfile | Build an image from source code |
| Inspect a running container | Monitor telemetry and health |
