GEMMA DEVELOPER AGENTSAVED EVIDENCE
← Dataset Exploration
ARCHIVED TRAINING / apiflask/apiflask

apiflask__apiflask-632

This is a preserved training example. Membership in the current training wave has not been verified.
apiflask/apiflask · Task 47 of 169

Problem statement

Specifying `headers` option in `@output` decorator generates invalid spec for OAS version >= 3.0.0
The OpenAPI Specification for versions 3.0.0 and higher indicates that the `Header` object must not specify either a `name` or an `in` field:
- 3.0.0: https://spec.openapis.org/oas/v3.0.0.html#header-object
- 3.1.0: https://spec.openapis.org/oas/v3.1.0.html#header-object

The current implementation introduced in #511 invokes `schema2parameters` from `apispec`, which leaves the fields in place, resulting in an invalid spec.

```python
import openapi_spec_validator
from apiflask import APIFlask, Schema
from marshmallow.fields import String


class Foo(Schema):
    name = String()


class ResponseHeader(Schema):
    x_token = String(data_key="X-Token", metadata={"description": "A custom token header"})


app = APIFlask(__name__)


@app.route("/foo")
@app.output(Foo, headers=ResponseHeader)
def foo():
    pass


client = app.test_client()
rv = client.get("/openapi.json")
assert rv.status_code == 200
openapi_spec_validator.validate(rv.json)  # Fails
```

The generated spec looks like this:

```json
{
    "components": {
        "schemas": {
            "Foo": {
                "properties": {
                    "name": {
                        "type": "string"
                    }
                },
                "type": "object"
            }
        }
    },
    "info": {
        "title": "APIFlask",
        "version": "0.1.0"
    },
    "openapi": "3.0.3",
    "paths": {
        "/foo": {
            "get": {
                "parameters": [],
                "responses": {
                    "200": {
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Foo"
                                }
                            }
                        },
                        "description": "Successful response",
                        "headers": {
                            "X-Token": {
                                "description": "A custom token header",
                                "in": "header",
                                "name": "X-Token",
                                "required": false,
                                "schema": {
                                    "type": "string"
                                }
                            }
                        }
                    }
                },
                "summary": "Foo"
            }
        }
    },
    "servers": [
        {
            "url": "http://localhost/"
        }
    ],
    "tags": []
}
```

I considered raising this against `apispec`, since in theory it might be possible to modify `schema2parameters` to not include `name` or `in` when the `location` value is `headers`, but the `name` value is still needed to populate the key of the `headers` dictionary in the spec, so I think it makes more sense to address in this project.


Environment:

- Python version: 3.11
- Flask version: 3.1.0
- APIFlask version: 2.3.0

Training membership

opd_e4b_cispo_v5 opd_e4b_pure_v6a opd_e4b_pure_v6b opd_e4b_pure_v7 opd_e4b_pure_v7b opd_e4b_self_audit_v4

Task issues extracted from preserved verified_rft_messages training examples. This is not a verified current RL wave manifest.

Task and snapshot provenance

Snapshot captured 2026-11-12T17:06:59.476467+00:00 · Autoresearch-Arena/gemma-4-developer-agent

{
  "datasets": [
    "opd_e4b_cispo_v5",
    "opd_e4b_pure_v6a",
    "opd_e4b_pure_v6b",
    "opd_e4b_pure_v7",
    "opd_e4b_pure_v7b",
    "opd_e4b_self_audit_v4"
  ],
  "examples": 31,
  "instance_id": "apiflask__apiflask-632",
  "problem_statement": "Specifying `headers` option in `@output` decorator generates invalid spec for OAS version >= 3.0.0\nThe OpenAPI Specification for versions 3.0.0 and higher indicates that the `Header` object must not specify either a `name` or an `in` field:\r\n- 3.0.0: https://spec.openapis.org/oas/v3.0.0.html#header-object\r\n- 3.1.0: https://spec.openapis.org/oas/v3.1.0.html#header-object\r\n\r\nThe current implementation introduced in #511 invokes `schema2parameters` from `apispec`, which leaves the fields in place, resulting in an invalid spec.\r\n\r\n```python\r\nimport openapi_spec_validator\r\nfrom apiflask import APIFlask, Schema\r\nfrom marshmallow.fields import String\r\n\r\n\r\nclass Foo(Schema):\r\n    name = String()\r\n\r\n\r\nclass ResponseHeader(Schema):\r\n    x_token = String(data_key=\"X-Token\", metadata={\"description\": \"A custom token header\"})\r\n\r\n\r\napp = APIFlask(__name__)\r\n\r\n\r\n@app.route(\"/foo\")\r\n@app.output(Foo, headers=ResponseHeader)\r\ndef foo():\r\n    pass\r\n\r\n\r\nclient = app.test_client()\r\nrv = client.get(\"/openapi.json\")\r\nassert rv.status_code == 200\r\nopenapi_spec_validator.validate(rv.json)  # Fails\r\n```\r\n\r\nThe generated spec looks like this:\r\n\r\n```json\r\n{\r\n    \"components\": {\r\n        \"schemas\": {\r\n            \"Foo\": {\r\n                \"properties\": {\r\n                    \"name\": {\r\n                        \"type\": \"string\"\r\n                    }\r\n                },\r\n                \"type\": \"object\"\r\n            }\r\n        }\r\n    },\r\n    \"info\": {\r\n        \"title\": \"APIFlask\",\r\n        \"version\": \"0.1.0\"\r\n    },\r\n    \"openapi\": \"3.0.3\",\r\n    \"paths\": {\r\n        \"/foo\": {\r\n            \"get\": {\r\n                \"parameters\": [],\r\n                \"responses\": {\r\n                    \"200\": {\r\n                        \"content\": {\r\n                            \"application/json\": {\r\n                                \"schema\": {\r\n                                    \"$ref\": \"#/components/schemas/Foo\"\r\n                                }\r\n                            }\r\n                        },\r\n                        \"description\": \"Successful response\",\r\n                        \"headers\": {\r\n                            \"X-Token\": {\r\n                                \"description\": \"A custom token header\",\r\n                                \"in\": \"header\",\r\n                                \"name\": \"X-Token\",\r\n                                \"required\": false,\r\n                                \"schema\": {\r\n                                    \"type\": \"string\"\r\n                                }\r\n                            }\r\n                        }\r\n                    }\r\n                },\r\n                \"summary\": \"Foo\"\r\n            }\r\n        }\r\n    },\r\n    \"servers\": [\r\n        {\r\n            \"url\": \"http://localhost/\"\r\n        }\r\n    ],\r\n    \"tags\": []\r\n}\r\n```\r\n\r\nI considered raising this against `apispec`, since in theory it might be possible to modify `schema2parameters` to not include `name` or `in` when the `location` value is `headers`, but the `name` value is still needed to populate the key of the `headers` dictionary in the spec, so I think it makes more sense to address in this project.\r\n\r\n\r\nEnvironment:\r\n\r\n- Python version: 3.11\r\n- Flask version: 3.1.0\r\n- APIFlask version: 2.3.0",
  "repo": "apiflask/apiflask",
  "source": "v2/experiments/train_data/opd_e4b_cispo_v5/verified_rft_messages.jsonl",
  "source_sha256": "a43610ad0dfb6ace95375cfae09000f41afc0338cc925af870a4ade7a9b20c4c"
}
{
  "captured_at": "2026-11-12T17:06:59.476467+00:00",
  "membership": "archived training",
  "membership_evidence": "Task issues extracted from preserved verified_rft_messages training examples. This is not a verified current RL wave manifest.",
  "name": "Preserved post-training task archive",
  "source": "Autoresearch-Arena/gemma-4-developer-agent",
  "source_revision": "016496de222aaafca0d4ee4c18efc63ba616f76e",
  "sources": [
    {
      "path": "v2/experiments/train_data/opd_e4b_cispo_v5/verified_rft_messages.jsonl",
      "sha256": "a43610ad0dfb6ace95375cfae09000f41afc0338cc925af870a4ade7a9b20c4c"
    },
    {
      "path": "v2/experiments/train_data/opd_e4b_hybrid_v3/verified_rft_messages.jsonl",
      "sha256": "bd326303eb127e8e5e08f03daf97bb88d79d19709d59f3f93f348bc56686a8df"
    },
    {
      "path": "v2/experiments/train_data/opd_e4b_onpolicy_v3/verified_rft_messages.jsonl",
      "sha256": "960c680e797e823a0d3a22f4b1d5ef60a72971373d703b877340b0c9126aaf68"
    },
    {
      "path": "v2/experiments/train_data/opd_e4b_pure_v6a/verified_rft_messages.jsonl",
      "sha256": "f045b7ca5b3883a1e2eaee81e1c02a4a1b53dd7b7b36e98bacb2ba5823a15148"
    },
    {
      "path": "v2/experiments/train_data/opd_e4b_pure_v6b/verified_rft_messages.jsonl",
      "sha256": "0f62460a9706eea5e1605255896f191ab00cb5706c5f1f2e1c293e9a718218dc"
    },
    {
      "path": "v2/experiments/train_data/opd_e4b_pure_v7/verified_rft_messages.jsonl",
      "sha256": "e37f7bd675322f3f81500b73559d60d5f602ca0537bf19f5cb06332c728c7b72"
    },
    {
      "path": "v2/experiments/train_data/opd_e4b_pure_v7b/verified_rft_messages.jsonl",
      "sha256": "b864bdc8695183433eef6e31cb8d33fad44ba3aded2170c1ade4ad5b2944ce23"
    },
    {
      "path": "v2/experiments/train_data/opd_e4b_self_audit_v4/verified_rft_messages.jsonl",
      "sha256": "0026023745afb8f3dc1c176dc7f7171157b4ad5a66656b524af218e8e19ceee6"
    },
    {
      "path": "v2/experiments/train_data/rft_e4b_aligned_v2/verified_rft_messages.jsonl",
      "sha256": "92a4515fee9d152b0d4c510ee3ce4caaaffe2003ba7584469f8027f174aab18c"
    },
    {
      "path": "v2/experiments/train_data/rft_v1/verified_rft_messages.jsonl",
      "sha256": "a42453ccd7ac7680b0a03865e8e7080bc8bf74c8d9d193b440c441ed46f8512b"
    },
    {
      "path": "v2/experiments/train_data/rft_v2/verified_rft_messages.jsonl",
      "sha256": "18f4b3bd7e651f83c6acab479c9475e3fa50dc652a384f309e97146983ac85ba"
    }
  ]
}