Skip to content

Troubleshooting

AddTelegramBot must be called before ...

Framework handler и transport APIs требуют Telegram bot services.

Правильный order:

builder.Services.AddTelegramBot(options => options.Token = token);
builder.Services.AddTelegramHandlersFromAssembly(typeof(Program).Assembly);
builder.Services.AddLongPolling();

Assembly does not contain generated Telegram handler metadata

AddTelegramHandlersFromAssembly(...) требует IWF.TeleFlow.Generators.

Исправление:

<PackageReference Include="IWF.TeleFlow.Generators" Version="..." PrivateAssets="all" />

Потом пересобери application.

Если generated registration не нужен, используй:

builder.Services.AddTelegramHandler<StartHandler>();

Или зарегистрируй module явно:

builder.Services.AddTelegramModule<AdminHandlers>();

Не переходи на deprecated reflection assembly registration как способ починить missing generated metadata.

TLF027: у handler нет route attribute

State и filter attributes ограничивают handler, но сами не route-ят updates.

Неправильно:

[State("registration:name")]
[HasText]
public Task Name(MessageContext ctx, CancellationToken ct)
{
    return Task.CompletedTask;
}

Правильно:

[Message]
[State("registration:name")]
[HasText]
public Task Name(MessageContext ctx, CancellationToken ct)
{
    return Task.CompletedTask;
}

Используй [Message], [Command], [Callback], [ChatMemberUpdated] или другой явный route attribute перед state и filter constraints.

Handler dependency was not registered

TeleFlow валидирует параметры handler methods до нормальной обработки updates. Если handler просит сервис, этот сервис должен быть зарегистрирован в DI:

public sealed class TicketHandler
{
    [CommandTemplate("ticket {id:long}")]
    public Task Ticket(
        MessageContext ctx,
        ITicketRepository tickets,
        CancellationToken ct)
    {
        // ...
    }
}

Зарегистрируй dependency до сборки приложения:

builder.Services.AddScoped<ITicketRepository, EfTicketRepository>();

То же правило действует для Telegram error handlers и custom filters.

Current update accessor падает вне обработки update

ITelegramCurrentUpdateAccessor scoped на один входящий Telegram update. Он работает внутри handlers, middleware и scoped services, до которых дошёл update pipeline.

Он не работает из application startup, background jobs, singleton services или кода, который выполняется до появления update.

Используй его из scoped services:

public sealed class UserService(ITelegramCurrentUpdateAccessor current)
{
    public long RequireUserId()
    {
        return current.User?.Id
            ?? throw new InvalidOperationException("Для этой операции нужен Telegram user.");
    }
}

Не внедряй его в singleton services.

Можно ли читать token из appsettings.json?

Да. TeleFlow не важно, откуда пришёл token. Прочитай его через обычную .NET configuration и явно передай resolved value:

builder.Services.AddTelegramBot(options =>
{
    options.Token = configuration["Telegram:BotToken"]
        ?? throw new InvalidOperationException("Telegram:BotToken is not configured.");
});

Смотри Конфигурация и секреты.

Handler не срабатывает

Проверь:

  • update type: message, callback, chat member;
  • command prefix;
  • text exact match vs contains;
  • state requirement;
  • class-level filters;
  • custom filter return value;
  • allowed updates for long polling.

State недоступен

Зарегистрируй state storage:

builder.Services.AddMemoryStateStorage();

Для custom storage убедись, что IStateStore и state middleware registered.

Wizard back не работает

Wizard back требует state history storage. AddMemoryStateStorage() его регистрирует. Custom storage должен предоставить IStateHistoryStore.

Callback data слишком длинная

Telegram callback data ограничен 64 UTF-8 bytes. Используй compact payloads:

[CallbackData("t")]
public sealed record TicketAction(long Id, string A);

Не клади large JSON payloads в callback data.

Callback data не смогла распаковаться

Если в логах есть Telegram callback data failed to deserialize, callback совпал с typed [Callback<TPayload>] route по compact prefix и количеству fields, но payload не удалось декодировать. Частые причины:

  • пользователь нажал старую inline-кнопку после изменения callback payload type;
  • numeric, boolean или enum field содержит invalid value;
  • другой компонент бота сгенерировал callback data с тем же prefix, но другим field format.

TeleFlow считает такой typed route не сматченным, поэтому raw callback fallback может ответить пользователю. Проектируй callback payloads так, чтобы они переживали версии: используй короткие стабильные prefixes, передавай IDs вместо больших объектов и заводи новый prefix, когда deployed callback shape меняется несовместимо.

Webhook возвращает unauthorized

Проверь SecretToken configuration и Telegram webhook settings. Incoming request должен использовать expected secret token.

Бот получает старые updates после рестарта

Telegram может вернуть pending updates после downtime. Current public API не документирует drop-pending-updates option. Deployment и startup behavior нужно проектировать с учётом pending updates.