gitbutlerapp/gitbutler · error

Invalid message format

Error message

Invalid message format

What it means

LoginService.finalizeAccount validates the JSON body returned by POST sessions/finalize before surfacing it as a success. If the response's `message` field is missing or not a string, it throws 'Invalid message format'. This is a server contract check: a 2xx response without the expected shape is treated as a failure rather than propagated blindly.

Solutions

  1. Inspect the actual 2xx response body of POST sessions/finalize (network tab) and confirm whether `message` is present and a string
  2. Verify you are talking to the expected backend environment and API version
  3. If the server is at fault, fix the endpoint to include a string `message` on success; if the client is stale, update the app
  4. If the server legitimately omits `message`, relax the validation to tolerate a missing message and use a default

Example fix

// before
(data) => {
  if (!isStr(data.message)) throw new Error("Invalid message format");
  return { message: data.message };
}
// after
(data) => ({ message: isStr(data.message) ? data.message : "Account finalized" })
Defensive patterns

Strategy: type-guard

Validate before calling

const res = await fetch(base + "sessions/finalize", { method: "POST", ... });
const data = await res.json();
if (res.ok && typeof data?.message !== "string") {
  console.warn("finalize returned unexpected shape", data);
}

Type guard

function hasMessage(data: unknown): data is { message: string } {
  return typeof data === "object" && data !== null && typeof (data as any).message === "string";
}

Try / catch

const result = await loginService.finalizeAccount(email, username);
if (result.type === "error") {
  if (result.errorMessage === "Invalid message format") {
    // 2xx body did not match the expected contract; log raw for diagnosis
    console.error("finalize: unexpected response shape", result.raw);
  }
  showError(result.errorMessage);
  return;
}

Prevention

When it happens

Trigger: The backend returns HTTP 200 for POST sessions/finalize with a JSON body that lacks a string `message` field (e.g. `{}` or `{message: 123}`), causing the successHandler's isStr(data.message) check to throw.

Common situations: Backend API changed and no longer returns `message` on success; a proxy/gateway returns an unexpected 2xx body (empty object, HTML converted to JSON); hitting a mock or wrong environment whose finalize endpoint returns a different shape; version mismatch between desktop app and backend.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18). Data as JSON: /api/errors/3d6926241e5272d5. Report an issue: GitHub.

Appendix: source

Thrown at packages/shared/src/lib/login/loginService.ts:117

				errorCode: "unknown_error",
				errorMessage: "An unknown error occurred",
				raw: error,
			};
		}
	}

	async finalizeAccount(
		email: string,
		username: string,
	): Promise<LoginResponse<{ message: string }>> {
		return await this.sendPostRequest(
			"sessions/finalize",
			{
				email,
				login: username,
			},
			(data) => {
				if (!isStr(data.message)) throw new Error("Invalid message format");
				return { message: data.message };
			},
		);
	}

	async confirmPasswordReset(
		token: string,
		newPassword: string,
		passwordConfirmation: string,
	): Promise<LoginResponse<{ message: string; token: string }>> {
		return await this.sendPostRequest(
			"sessions/confirm_new_password",
			{
				password_reset_token: token,
				password: newPassword,
				password_confirmation: passwordConfirmation,
			},
			(data) => {

View on GitHub (pinned to 58e5313667)