Skip to content

Invalid modality input causes 500 and DSCProcessor returns hardcoded string #35

@Devguru-codes

Description

@Devguru-codes

Locations

  • apps/backend/app/routers/reports.py:32,82 (Input validation)
  • package/src/pyaslreport/modalities/testdsc/processor.py:17-30 (DSC Placeholder)

Description

Two sub-issues: (1) Passing an invalid modality string (e.g., "xyz") to either BIDS or DICOM endpoint causes ModalityTypeValues("xyz") to raise an uncaught ValueError, returning an unhelpful 500 error. (2) The DSCProcessor returns a hardcoded string "dsc data" instead of a dict, breaking the endpoint's response_model=dict contract.

Reproduction (on main branch)

Automated Results on main branch

# Test Status Detail
T1 Valid modality 'ASL' accepted (no 500) PASS
T2 Invalid modality 'xyz' on /bids → 422 FAIL Status=500
T3 Invalid modality 'INVALID' on /dicom → 422 FAIL Status=400
T4 No modality → defaults to ASL PASS
T5 DSCProcessor returns dict FAIL Got string 'dsc data'

Summary: PASSED=2 FAILED=3

API Responses on main

POST /api/report/process/bids modality=xyz → Status: 500
POST /api/report/process/dicom modality=INVALID → Status: 400 (file check ran first)
DSCProcessor.process() → type=str, value='dsc data'

Code to reproduce this -

"""Bug 4 reproduction: Modality Processing Flaws (Input Validation & DSC Placeholder)"""
import sys, os, json
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'apps', 'backend'))
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'package', 'src'))

from unittest.mock import MagicMock
sys.modules['weasyprint'] = MagicMock()

from fastapi.testclient import TestClient
from app.main import app
client = TestClient(app, raise_server_exceptions=False)

results = []

# ========== Sub-issue 1: Invalid modality input validation ==========

# T1: Valid modality "ASL" should work (returns 400 for no files, not 500 for bad modality)
r1 = client.post("/api/report/process/bids", data={"modality": "ASL"})
ok1 = r1.status_code in (200, 400)
results.append({"test": "T1: Valid modality 'ASL' accepted (no 500)",
                "pass": ok1,
                "detail": "" if ok1 else f"Status={r1.status_code}"})

# T2: Invalid modality "xyz" on BIDS endpoint should return 422 (not 500)
r2 = client.post("/api/report/process/bids", data={"modality": "xyz"})
ok2 = r2.status_code == 422
results.append({"test": "T2: Invalid modality 'xyz' on /bids returns 422 (not 500)",
                "pass": ok2,
                "detail": "" if ok2 else f"Status={r2.status_code}"})

# T3: Invalid modality on DICOM endpoint should also return 422 (not 400 for missing files first)
r3 = client.post("/api/report/process/dicom", data={"modality": "INVALID"})
ok3 = r3.status_code == 422
results.append({"test": "T3: Invalid modality 'INVALID' on /dicom returns 422 (not 400/500)",
                "pass": ok3,
                "detail": "" if ok3 else f"Status={r3.status_code}"})

# T4: Empty modality defaults to ASL (should not crash)
r4 = client.post("/api/report/process/bids")
ok4 = r4.status_code in (200, 400)
results.append({"test": "T4: No modality provided defaults to ASL (no crash)",
                "pass": ok4,
                "detail": "" if ok4 else f"Status={r4.status_code}"})

# ========== Sub-issue 2: DSC Processor placeholder ==========

# T5: DSC modality should return a proper dict, not a hardcoded string
from pyaslreport.modalities.testdsc.processor import DSCProcessor
proc = DSCProcessor({"modality": "DSC", "files": [], "nifti_file": None, "dcm_files": []})
result = proc.process()
ok5 = isinstance(result, dict)
results.append({"test": "T5: DSCProcessor.process() returns dict (not hardcoded string)",
                "pass": ok5,
                "detail": "" if ok5 else f"Got type={type(result).__name__}, value={repr(result)}"})

# ========== Print results ==========
passed = sum(1 for r in results if r["pass"])
failed = sum(1 for r in results if not r["pass"])
print(f"PASSED={passed} FAILED={failed}")
for r in results:
    status = "PASS" if r["pass"] else "FAIL"
    detail = f" -- {r['detail']}" if r["detail"] else ""
    print(f"  [{status}] {r['test']}{detail}")

with open(os.path.join(os.path.dirname(__file__), 'results.json'), 'w') as f:
    json.dump({"passed": passed, "failed": failed, "results": results}, f, indent=2)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    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