# Known Limitations

This page collects the behavioral limits and defects in the current code that affect deployment and use, each with its location.

## Error-Handling Defects

| Location | Behavior | Impact |
|---|---|---|
| `handlers/PostToPath.go` type check | An unsupported type sets only `errMessage`, leaving `err` nil; `HandleError` calls `err.Error()` and panics | gin Recovery returns `500` instead of the intended `400` |
| `handlers/GetFromPath.go` decode | After `vips.NewImageFromBuffer` fails, the error is sent but there is no `return`, and the nil image is used next | The panic happens inside a goroutine that gin Recovery cannot catch, so the whole process exits |
| `handlers/GetFromPath.go` `streamImage` | Calls itself when the ResponseWriter does not implement `http.Flusher` | Infinite recursion; Gin's default ResponseWriter implements `Flusher`, so normal deployments do not hit it |

## Concurrency and Timeouts

All three handlers use unbuffered result channels. After a timeout returns `408`, nothing receives the result, so the background goroutine blocks forever on its send; the upload and read goroutines also keep touching `gin.Context` after the handler has returned.

## Caching

| Limitation | Details |
|---|---|
| Delete does not purge | After the original moves to the trash, transforms in `storage/image/cache/` are still served (see [Caching Layers](/caching#invalidation)) |
| Unnormalized cache key | `q=75` and no `q` produce identical output but two cache files |
| Extension collision | Cache filenames drop the original extension, so `photo.jpg` and `photo.png` in one folder share a cache file when read with the same parameters |
| No size cap | Local cache files never expire or get evicted |

## Security and Deployment

| Limitation | Details |
|---|---|
| No authentication | The Go service does not authenticate upload or delete requests; the Nginx allowlist ships commented out |
| Unconstrained paths | Upload and delete build paths with `filepath.Join` without checking the result stays inside `storage/image/upload/` |
| Header-only type check | Upload type comes from the part's `Content-Type`; file contents are not inspected |
| Placeholders not in repo | The `**/image/` rule in `.gitignore` excludes `app/internal/assets/image/`; supply `404-light.svg` / `404-dark.svg` yourself |
| Status code on failure | A failed read returns the placeholder via `c.File` with HTTP `200`, not `404` |
