Component
Python SDK
Infrahub SDK version
1.9.0b0 (submodule commit 44a7cccf57ee3e20a2f7946b9e505135b5d7387a, pinned by Infrahub release-1.9)
Current Behavior
All three file_object_content* Jinja2 filters shipped in opsmill/infrahub-sdk-python#889 and #904 fail at runtime with HTTP 404. The SDK constructs URLs under /api/files/..., but the Infrahub backend only routes these endpoints under /api/storage/files/.... Every call to file_object_content, file_object_content_by_id, or file_object_content_by_hfid raises JinjaFilterError: Client error '404 Not Found', and the corresponding artifact goes to Error status.
SDK URLs in infrahub_sdk/object_store.py (commit 44a7ccc):
```
line 105: f"{self.client.address}/api/files/by-storage-id/{storage_id}"
line 110: f"{self.client.address}/api/files/{node_id}"
line 116: f"{self.client.address}/api/files/by-hfid/{kind}?{params}"
line 191: (sync) same
line 196: (sync) same
line 202: (sync) same
```
Backend actual routes (from /api/openapi.json):
```
/api/storage/files/by-storage-id/{storage_id}
/api/storage/files/{node_id}
/api/storage/files/by-hfid/{kind}
```
A raw curl confirms:
```
curl /api/files/by-storage-id/ → HTTP 404 "endpoint does not exist"
curl /api/storage/files/by-storage-id/ → HTTP 200, returns file content
```
The /api/files/* prefix is not mounted anywhere in the server. The SDK's own unit tests at tests/unit/sdk/test_infrahub_filters.py hard-code the wrong URL (`FILE_BY_STORAGE_ID_URL = "http://mock/api/files/by-storage-id\"\`) in their mocks, so the test suite passes against the wrong contract — this is how the bug shipped unnoticed.
The bug has been present since the filters were introduced (PRs #889 and #904) and is still on the latest tip of `origin/infrahub-develop` (commit `a203aac`); the diff of `object_store.py` between the release-1.9 pin and that tip is empty.
Expected Behavior
- `file_object_content(storage_id)` returns the file's raw content for a valid `CoreFileObject` storage_id.
- `file_object_content_by_id(node_id)` returns the file's raw content for a valid node UUID.
- `file_object_content_by_hfid(hfid, kind=...)` returns the file's raw content for a valid HFID.
- SDK unit tests assert the correct URL (`/api/storage/files/...`) so that contract drift is caught.
Steps to Reproduce
-
Start Infrahub 1.9 (e.g. `uv run invoke demo.start` against `release-1.9`).
-
Load a schema that extends `CoreFileObject`, e.g. `TestingFileBlob` with a `label` attribute.
-
Upload a file object via the GraphQL multipart mutation:
```graphql
mutation CreateBlob($file: Upload!) {
TestingFileBlobCreate(data: {label: {value: "blob_a"}}, file: $file) {
object { id, hfid, storage_id { value } }
}
}
```
-
Register a Git repo with a Jinja2 transform containing any of:
```jinja
{{ '<storage_id>' | file_object_content }}
{{ '<node_id>' | file_object_content_by_id }}
{{ '' | file_object_content_by_hfid(kind='TestingFileBlob') }}
```
-
Observe the artifact status → `Error`. Worker logs contain:
```
JinjaFilterError: Filter 'file_object_content': failed to retrieve content for storage_id:
— Client error '404 Not Found' for url 'http://server:8000/api/files/by-storage-id/'
```
Additional Information
Suggested fix (minimal): change six lines in `infrahub_sdk/object_store.py` to use `/api/storage/files/` prefix. Also update `tests/unit/sdk/test_infrahub_filters.py` to match the correct URL, otherwise the tests will silently pass against a regressed contract.
Alternative: add an `/api/files/*` alias router in the Infrahub backend. Cleaner external URL surface, but loses the `storage/` grouping that matches the rest of that namespace.
Detection gap: the SDK's unit tests use mocks that match the buggy URLs. An integration test that exercises each filter end-to-end against a live backend would have caught this at PR review.
Full analysis and test log: `dev/specs/infp-504-artifact-composition/test-report.md` in opsmill/infrahub release-1.9.
Related: INFP-504, IFC-2275, opsmill/infrahub PR #8705.
Component
Python SDK
Infrahub SDK version
1.9.0b0 (submodule commit
44a7cccf57ee3e20a2f7946b9e505135b5d7387a, pinned by Infrahub release-1.9)Current Behavior
All three
file_object_content*Jinja2 filters shipped in opsmill/infrahub-sdk-python#889 and #904 fail at runtime with HTTP 404. The SDK constructs URLs under/api/files/..., but the Infrahub backend only routes these endpoints under/api/storage/files/.... Every call tofile_object_content,file_object_content_by_id, orfile_object_content_by_hfidraisesJinjaFilterError: Client error '404 Not Found', and the corresponding artifact goes toErrorstatus.SDK URLs in
infrahub_sdk/object_store.py(commit44a7ccc):```
line 105: f"{self.client.address}/api/files/by-storage-id/{storage_id}"
line 110: f"{self.client.address}/api/files/{node_id}"
line 116: f"{self.client.address}/api/files/by-hfid/{kind}?{params}"
line 191: (sync) same
line 196: (sync) same
line 202: (sync) same
```
Backend actual routes (from
/api/openapi.json):```
/api/storage/files/by-storage-id/{storage_id}
/api/storage/files/{node_id}
/api/storage/files/by-hfid/{kind}
```
A raw
curlconfirms:```
curl /api/files/by-storage-id/ → HTTP 404 "endpoint does not exist"
curl /api/storage/files/by-storage-id/ → HTTP 200, returns file content
```
The
/api/files/*prefix is not mounted anywhere in the server. The SDK's own unit tests attests/unit/sdk/test_infrahub_filters.pyhard-code the wrong URL (`FILE_BY_STORAGE_ID_URL = "http://mock/api/files/by-storage-id\"\`) in their mocks, so the test suite passes against the wrong contract — this is how the bug shipped unnoticed.The bug has been present since the filters were introduced (PRs #889 and #904) and is still on the latest tip of `origin/infrahub-develop` (commit `a203aac`); the diff of `object_store.py` between the release-1.9 pin and that tip is empty.
Expected Behavior
Steps to Reproduce
Start Infrahub 1.9 (e.g. `uv run invoke demo.start` against `release-1.9`).
Load a schema that extends `CoreFileObject`, e.g. `TestingFileBlob` with a `label` attribute.
Upload a file object via the GraphQL multipart mutation:
```graphql
mutation CreateBlob($file: Upload!) {
TestingFileBlobCreate(data: {label: {value: "blob_a"}}, file: $file) {
object { id, hfid, storage_id { value } }
}
}
```
Register a Git repo with a Jinja2 transform containing any of:
```jinja
{{ '<storage_id>' | file_object_content }}
{{ '<node_id>' | file_object_content_by_id }}
{{ '' | file_object_content_by_hfid(kind='TestingFileBlob') }}
```
Observe the artifact status → `Error`. Worker logs contain:
```
JinjaFilterError: Filter 'file_object_content': failed to retrieve content for storage_id:
— Client error '404 Not Found' for url 'http://server:8000/api/files/by-storage-id/'
```
Additional Information
Suggested fix (minimal): change six lines in `infrahub_sdk/object_store.py` to use `/api/storage/files/` prefix. Also update `tests/unit/sdk/test_infrahub_filters.py` to match the correct URL, otherwise the tests will silently pass against a regressed contract.
Alternative: add an `/api/files/*` alias router in the Infrahub backend. Cleaner external URL surface, but loses the `storage/` grouping that matches the rest of that namespace.
Detection gap: the SDK's unit tests use mocks that match the buggy URLs. An integration test that exercises each filter end-to-end against a live backend would have caught this at PR review.
Full analysis and test log: `dev/specs/infp-504-artifact-composition/test-report.md` in opsmill/infrahub release-1.9.
Related: INFP-504, IFC-2275, opsmill/infrahub PR #8705.