Skip to content

fix(tasks): GET /tasks deserialization is inverted; returns empty Vec on real responses #74

@joshrotenberg

Description

@joshrotenberg

Summary

TasksHandler::get_all_tasks() deserializes the wrong response shape and silently falls back to an empty Vec for any non-array body — including the API's actual response shape.

Expected behavior

Per the OpenAPI spec, GET /tasks returns:

```json
{
"tasks": [
{ "taskId": "...", "status": "...", ... }
],
"links": [...]
}
```

The Rust side should deserialize this into something like `TasksStateUpdate { tasks: Vec, links: Vec }` and `get_all_tasks` should return `Vec`.

Actual behavior

src/tasks.rs:131-139 expects a bare array:

```rust
let response: serde_json::Value = self.client.get_raw("/tasks").await?;
match response {
serde_json::Value::Array(arr) => Ok(serde_json::from_value(arr.into())?),
_ => Ok(Vec::new()), // <-- silently swallows the real shape
}
```

For the API's wrapper response ({tasks: [...], links: [...]}), the match falls through to the empty-Vec branch.

Impact

  • get_all_tasks() returns Ok(vec![]) regardless of actual task state. Any caller using this for status polling or auditing is silently blind.
  • Defensive empty-vec branch masks real deserialization breakage if the spec changes (no error surfaced).

Relevant code

  • src/tasks.rs:131-139
  • Spec: tests/fixtures/cloud_openapi.json — search for /tasks GET response → TasksStateUpdate schema

Suggested fix

Either:

  1. Define a proper TasksStateUpdate wrapper struct, change return type, and document. Aligns with refactor(types): consolidate shared task/tag/link models and normalize task status typing #64 (canonical task types).
  2. Or unwrap the tasks array internally and keep Vec<TaskStateUpdate> return type, but return an explicit CloudError on shape mismatch (no silent fallback).

Option 1 is preferred — exposes the wrapper for callers who want links/pagination, and the canonical types from #64 fall in cleanly.

Acceptance criteria

  • get_all_tasks() correctly deserializes the wrapper response shape
  • Mock test with the realistic shape (use tests/fixtures/cloud_openapi.json examples or a fixture file)
  • No silent empty-Vec fallback — shape mismatches return CloudError::Deserialization
  • Doctests in tasks.rs updated

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions