gotify/server · error
file with key 'file' must be present
Error message
file with key 'file' must be present
What it means
The image-upload endpoint requires a multipart form field named exactly 'file'. When the multipart request contains no file under that key, gin's ctx.FormFile returns http.ErrMissingFile and the handler converts it into this 400 error. It is the API's way of saying the required upload part is absent.
Source
Thrown at api/application.go:417
// $ref: "#/definitions/Error"
// 404:
// description: Not Found
// schema:
// $ref: "#/definitions/Error"
// 500:
// description: Server Error
// schema:
// $ref: "#/definitions/Error"
func (a *ApplicationAPI) UploadApplicationImage(ctx *gin.Context) {
withID(ctx, "id", func(id uint) {
app, err := a.DB.GetApplicationByID(id)
if success := successOrAbort(ctx, 500, err); !success {
return
}
if app != nil && app.UserID == auth.GetUserID(ctx) {
file, err := ctx.FormFile("file")
if err == http.ErrMissingFile {
ctx.AbortWithError(400, errors.New("file with key 'file' must be present"))
return
} else if err != nil {
ctx.AbortWithError(500, err)
return
}
head := make([]byte, 261)
open, _ := file.Open()
open.Read(head)
if !filetype.IsImage(head) {
ctx.AbortWithError(400, errors.New("file must be an image"))
return
}
ext := filepath.Ext(file.Filename)
if !ValidApplicationImageExt(ext) {
ctx.AbortWithError(400, errors.New("invalid file extension"))
return
}View on GitHub (pinned to 14bfc25627)
Solutions
- Send the file in multipart/form-data under the exact key 'file' (FormData.append('file', file))
- With curl use: curl -F "file=@/path/to/img.png" ...
- Verify the request Content-Type is multipart/form-data and the body is not JSON
- Check client code/libraries that the field name was not renamed
Example fix
// before
const fd = new FormData();
fd.append('image', file);
fetch('/applications/1/image', {method:'POST', body: fd});
// after
const fd = new FormData();
fd.append('file', file);
fetch('/applications/1/image', {method:'POST', body: fd}); Defensive patterns
Strategy: validation
Validate before calling
const fd = new FormData();
if (!file) throw new Error('a file is required');
fd.append('file', file, file.name);
console.log(fd.get('file')); // must be non-null under key 'file' Try / catch
try {
await api.post(`/applications/${id}/image`, fd);
} catch (e) {
if (e.response?.status === 400 && e.response?.data?.includes("must be present")) {
// ensure multipart part is named 'file' and retry
} else throw e;
} Prevention
- Always append the upload as FormData key 'file', matching the server's ctx.FormFile("file")
- Verify Content-Type is multipart/form-data; never override it with application/json for uploads
- Log the FormData entries before sending in tests
- Check the server handler's expected field name whenever integrating a new upload endpoint
When it happens
Trigger: POSTing to the upload route with multipart/form-data that lacks a part named 'file'; sending JSON instead of multipart; sending the file under a different field name such as 'image' or 'upload'; sending an empty file part.
Common situations: Frontend FormData.append('image', f) instead of append('file', f); using curl -F without the right key; clients sending application/json bodies; axios default content-type overriding multipart; testing tools omitting the file.
Related errors
- invalid file extension
- cannot delete internal application
- file must be an image
- sort key is not unique
- invalid id
AI-assisted analysis of gotify/server@14bfc25627 (2026-09-05).
Data as JSON: /api/errors/79f2d1563cd54e98.
Report an issue: GitHub.