gotify/server · warning
application does not exists
Error message
application does not exists
What it means
An HTTP 404 raised by the DeleteMessages endpoint when the application for the given path ID is nil or is owned by a different user. Only the owner may delete an application's messages; the library returns 404 (not 403) in both the missing and not-owned cases. The message string contains a typo ('exists' vs 'exist') compared to the sibling error at message.go:191, but the semantics are identical.
Source
Thrown at api/message.go:264
// $ref: "#/definitions/Error"
// 403:
// description: Forbidden
// schema:
// $ref: "#/definitions/Error"
// 404:
// description: Not Found
// schema:
// $ref: "#/definitions/Error"
func (a *MessageAPI) DeleteMessageWithApplication(ctx *gin.Context) {
withID(ctx, "id", func(id uint) {
application, err := a.DB.GetApplicationByID(id)
if success := successOrAbort(ctx, 500, err); !success {
return
}
if application != nil && application.UserID == auth.GetUserID(ctx) {
successOrAbort(ctx, 500, a.DB.DeleteMessagesByApplication(id))
} else {
ctx.AbortWithError(404, errors.New("application does not exists"))
}
})
}
// DeleteMessage deletes a message with an id.
// swagger:operation DELETE /message/{id} message deleteMessage
//
// Deletes a message with an id.
//
// ---
// produces: [application/json]
// security: [clientTokenAuthorizationHeader: [], clientTokenHeader: [], clientTokenQuery: [], basicAuth: []]
// parameters:
// - name: id
// in: path
// description: the message id
// required: true
// type: integerView on GitHub (pinned to 14bfc25627)
Solutions
- Confirm the application ID exists and is yours via GET /application before deleting its messages.
- Treat a 404 here after a successful delete as success (idempotency): messages are already gone.
- If the whole application was removed, skip the message-delete step entirely.
- Check the script is authenticated as the owning user, not another account.
Example fix
// before
await fetch(`/application/${appId}/message`, { method: 'DELETE' });
await fetch(`/application/${appId}/message`, { method: 'DELETE' }); // second call -> 404 'application does not exists'
// after
const res = await fetch(`/application/${appId}/message`, { method: 'DELETE' });
if (res.status === 404) console.log('already deleted or not owned — treat as success'); Defensive patterns
Strategy: validation
Validate before calling
// Confirm ownership before issuing the bulk delete
const apps = await fetch('/application', { headers: { 'X-Gotify-Key': token } }).then(r => r.json());
if (!apps.some(a => a.id === appId)) {
console.log(`skip: application ${appId} already gone or not owned`);
return; // treat as already-deleted
} Try / catch
// Make bulk delete idempotent
const res = await fetch(`/application/${appId}/message`, { method: 'DELETE' });
if (res.status === 404) return; // already deleted or not owned — goal state reached
if (!res.ok) throw new Error(`bulk delete failed: ${res.status}`); Prevention
- Treat 404 from this endpoint as success in cleanup/CI scripts to survive double-deletes.
- Delete message state before deleting the application itself in teardown scripts.
- Capture application IDs fresh from GET /application, not from stale config.
- 404 covers 'not owned' too — verify you authenticate as the owner before assuming deletion failed.
When it happens
Trigger: DELETE /application/{id}/message (delete all messages of an application) where the ID (1) does not exist, (2) refers to an already-deleted application, or (3) belongs to another user. Double-deletion is a classic trigger: the first DELETE succeeds, the second hits this 404.
Common situations: Retry logic re-running a delete that already succeeded; cleanup scripts iterating IDs captured before deletion; deleting messages of another user's application; wrong instance/environment in CI scripts.
Related errors
AI-assisted analysis of gotify/server@14bfc25627 (2026-09-05).
Data as JSON: /api/errors/5cfc4cffc2e08e60.
Report an issue: GitHub.