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: integer

View on GitHub (pinned to 14bfc25627)

Solutions

  1. Confirm the application ID exists and is yours via GET /application before deleting its messages.
  2. Treat a 404 here after a successful delete as success (idempotency): messages are already gone.
  3. If the whole application was removed, skip the message-delete step entirely.
  4. 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

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.