louislam/uptime-kuma · info · Error
user not found, have you installed?
Error message
user not found, have you installed?
What it means
Thrown locally by autoGetBaleChatID (Bale.vue:97) when the newest entry returned by Bale's bot getUpdates endpoint is an update type the code does not recognize. The handler only reads update.channel_post and update.message; any other update shape sitting on top of the result stack (callback_query, edited_message, my_chat_member, poll, chat_member, etc.) makes both branches miss and the code throws this Error. It is immediately caught and shown as a red toast, so it is a controlled user-facing message rather than a crash.
Source
Thrown at extra/remove-2fa.js:23
const { R } = require("redbean-node");
const readline = require("readline");
const TwoFA = require("../server/2fa");
const args = require("args-parser")(process.argv);
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
const main = async () => {
Database.initDataDir(args);
await Database.connect();
try {
// No need to actually reset the password for testing, just make sure no connection problem. It is ok for now.
if (!process.env.TEST_BACKEND) {
const user = await R.findOne("user");
if (!user) {
throw new Error("user not found, have you installed?");
}
console.log("Found user: " + user.username);
let ans = await question("Are you sure want to remove 2FA? [y/N]");
if (ans.toLowerCase() === "y") {
await TwoFA.disable2FA(user.id);
console.log("2FA has been removed successfully.");
}
}
} catch (e) {
console.error("Error: " + e.message);
}
await Database.close();
rl.close();
View on GitHub (pinned to 6b5ea01557)
Solutions
- Send a brand-new plain message (or /start) to the bot or target channel in Bale, wait a moment, then click 'Auto Get' again so a message/channel_post update is the newest one.
- If the queue is polluted, clear it by calling getUpdates with an offset past the last update_id (or delete and recreate the webhook), then retry Auto Get.
- Make the handler tolerant: also read chat.id from edited_message.chat.id, my_chat_member.chat.id, and callback_query.message.chat.id so non-message updates still yield an ID.
- Scan res.data.result from the newest entry backwards and pick the first update that carries any recognizable chat object, instead of only inspecting the single last entry.
Example fix
// before
if (update.channel_post) {
this.$parent.notification.baleChatID = update.channel_post.chat.id;
} else if (update.message) {
this.$parent.notification.baleChatID = update.message.chat.id;
} else {
throw new Error(this.$t("chatIDNotFound"));
}
// after: also accept other update shapes that still carry a chat
let chatId =
update.channel_post?.chat.id ??
update.message?.chat.id ??
update.edited_message?.chat.id ??
update.my_chat_member?.chat.id ??
update.callback_query?.message?.chat.id;
if (chatId != null) {
this.$parent.notification.baleChatID = chatId;
} else {
throw new Error(this.$t("chatIDNotFound"));
} Defensive patterns
Strategy: type-guard
Validate before calling
// Before calling axios, confirm a token is set so getUpdates is even valid
if (!this.$parent.notification.baleBotToken || !this.$parent.notification.baleBotToken.trim()) {
this.$root.toastError(this.$t("baleBotTokenRequired"));
return;
} Type guard
// Narrow a raw Bale/Telegram update to one that exposes a chat.id
function hasChatId(update) {
return Boolean(
update?.channel_post?.chat?.id ??
update?.message?.chat?.id ??
update?.edited_message?.chat?.id ??
update?.my_chat_member?.chat?.id ??
update?.callback_query?.message?.chat?.id
);
}
// usage inside autoGetBaleChatID
const update = res.data.result[res.data.result.length - 1];
if (!hasChatId(update)) {
throw new Error(this.$t("chatIDNotFound"));
} Try / catch
// Keep the single try/catch, but classify so the toast is specific
try {
const res = await axios.get(this.baleGetUpdatesURL("withToken"));
const update = res.data?.result?.[res.data.result.length - 1];
if (!hasChatId(update)) throw new Error(this.$t("chatIDNotFound"));
this.$parent.notification.baleChatID =
update.channel_post?.chat.id ?? update.message?.chat.id;
} catch (error) {
// Distinguish network/HTTP errors from the local chatIDNotFound
const msg = error.response
? `${this.$t("chatIDNotFound")} (HTTP ${error.response.status})`
: error.message;
this.$root.toastError(msg);
} Prevention
- Send a fresh message to the bot immediately before clicking 'Auto Get' so a message/channel_post is guaranteed to be the newest update.
- Drain the bot's update queue (getUpdates with offset, or deleteWebhook) before running auto-detect in a CI/test environment.
- Never run auto-detect while a webhook is registered for the same bot token.
- Extend hasChatId-style narrowing before reading update fields so unhandled update types degrade gracefully instead of throwing.
When it happens
Trigger: Clicking the 'Auto Get' button next to bale-chat-id after the bot's last received update was NOT a plain message or channel post. Concretely: a user pressed an inline button (callback_query), edited or forwarded an earlier message (edited_message), the bot was added/removed from a chat (my_chat_member / chat_member), or a poll-related update landed last. Each leaves res.data.result populated but the top item has no .channel_post and no .message key, so the else branch at line 97 fires.
Common situations: Bot freshly added to a group (Bale emits my_chat_member), which then sits above the real /start message. A user editing a previously sent message pushes an edited_message update on top. A conflicting webhook or a prior getUpdates call with offset already consumed the real messages, leaving only member/poll updates. Long-running bots whose update queue has accreted non-message events.
Related errors
- user not found, have you installed?
- Password is too weak, please use a stronger password.
- Invalid db-config.json, it must be an object
- SMSEagle API returned error: ${resp.data}
- SMSEagle API returned an empty response
AI-assisted analysis of louislam/uptime-kuma@6b5ea01557 (2026-08-12).
Data as JSON: /api/errors/e104f9fe4e3111a3.
Report an issue: GitHub.