Skip to content

fix(webspace-files): unwrap daemon-wrapped data payload to prevent double-nesting - #223

Merged
NaysKutzu merged 1 commit into
MythicalLTD:developfrom
Crackhead-gsk:fix/webspace-files-double-nested-data
Sep 5, 2026
Merged

NaysKutzu merged 1 commit into
MythicalLTD:developfrom
Crackhead-gsk:fix/webspace-files-double-nested-data

Conversation

@Crackhead-gsk

Copy link
Copy Markdown

Summary

Fixes the WebSpace file manager showing "No Files Found" even when the
WebSpace actually contains files.

Root cause

WebSpaceFilesController::daemonResponse() always forwards the FeatherQuilld
daemon's raw response body into ApiResponse::success(). FeatherQuilld
daemon endpoints are inconsistent in their own response shape:

  • Some return a bare payload, e.g. {"ok": true} or
    {"ok": true, "data": {"path": "..."}}.
  • Others (list / search / pull-jobs) wrap their entire payload in a single
    "data" key with nothing else alongside it, e.g. {"data": [...]} or
    {"data": {"entries": [...], "total": 4, "page": 1, "per_page": 250}}.

ApiResponse::success() always wraps whatever it's given in another
top-level "data" key. For the second group above this produces a doubly
nested response: {"data": {"data": [...]}}. The frontend reads
response.data expecting the actual list/object directly, so it received
the wrapper object instead — resulting in an empty-looking file manager even
though the daemon returned real file entries.

Fix

Unwrap the daemon's own "data" key in daemonResponse(), but only when:

  • it is the sole top-level key in the daemon body, and
  • its value is itself an array/object.

This collapses the double envelope for list/search/pull-jobs-style
responses while leaving untouched:

  • endpoints that pair "data" with sibling keys (e.g. {"ok": true, "data": {...}})
  • endpoints whose "data" value is a bare scalar (e.g. files/contents
    returning {"data": "<file text>"}), which the frontend already reads as
    response.data.data for the file editor.

Testing

Reproduced and verified live against a real FeatherQuilld node + WebSpace:

  • Before: GET /api/user/webspaces/{uuid}/files/list?directory=/&page=1&per_page=250
    returned {"data": {"data": {"entries": [...]}}} and the file manager UI
    showed "No Files Found" for a WebSpace with 4 real files.
  • After: same request returns {"data": {"entries": [...], "total": 4, ...}}
    and the file manager correctly lists all files.
  • Verified files/contents (file editor) still works correctly (unaffected,
    since its daemon body's "data" value is a scalar string).
  • Verified files/create-directory ({"ok": true} shape) still works
    correctly and is unaffected by the unwrap condition.
  • Verified files/pull-jobs ({"data": {"downloads": []}} shape) unwraps
    correctly to {"data": {"downloads": []}} with no double nesting.

No automated test suite changes; this is a minimal, scoped fix to a single
private helper method used by every WebSpaceFilesController daemon-backed
endpoint.

…uble-nesting

FeatherQuilld daemon endpoints inconsistently return either a bare
payload ({"ok": true}) or wrap their entire payload in a "data" key
(list/search/pull-jobs return {"data": [...]} or
{"data": {"entries": [...]}}).

WebSpaceFilesController::daemonResponse() always forwarded the full
daemon body into ApiResponse::success(), which itself always wraps
its argument in another "data" key. For endpoints in the second
group this produced a doubly-nested {"data": {"data": [...]}}
response. The frontend reads response.data expecting the actual
list/object and got the wrapper instead, so the file manager showed
"No Files Found" even when the WebSpace had files.

Unwrap the daemon's own "data" key only when it is the sole
top-level key and itself an array, so paginated/list-style responses
collapse to a single envelope while endpoints that pair "data" with
sibling keys (e.g. "ok") or return a bare scalar under "data" (e.g.
files/contents returning file text, which the frontend already reads
as response.data.data) are left untouched.
@coderabbitai

coderabbitai Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Team

Run ID: 33cbb3e9-2ef6-4993-8b88-9c02e26d6043

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@NaysKutzu
NaysKutzu merged commit 8eac0a0 into MythicalLTD:develop Sep 5, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants