Skip to content

[Bug]:v1.4.0: chat input disabled after first turn (regression); v1.4.0b0: hardcoded URL guard breaks matching deployments #520

@leval907

Description

@leval907

Do you need to file an issue?

  • I have searched the existing issues and this bug is not already filed.
  • I believe this is a legitimate bug, not just a question or feature request.

Describe the bug

We discovered two distinct frontend regressions in the 1.4.0 release series. Both are independently reproducible. Reporting together since investigation revealed them in tandem.


Bug 1: Chat input field stays disabled after the first turn (1.4.0)

Version: deeptutor==1.4.0 (PyPI, released 2026-05-22) Deployment: packaged Next.js frontend launched via deeptutor startnext-server v16.2.3.

Symptom: After the first user→assistant turn renders correctly, the chat input field becomes permanently disabled. The "Send" button is greyed out. Opening a new chat does not help — input is disabled there too. Hard refresh + incognito + clearing site data do not restore it.

Backend is healthy:

  • Turn writes correctly to data/user/chat_history.db: status completed, assistant message stored (verified e.g. 1431 chars of valid RAG-grounded answer).
  • Last event in turn_events: done with status: completed. Sequence is clean: thinking → content → stage_end → sources → result → done.
  • journalctl -u deeptutor shows no error / warning at the time of the failed second submit.

Network observations (DevTools):

  • WebSocket /api/v1/ws connection is established and stays open.
  • wsm.sessionActivated / wsm.sessionDeactivated frames are visible.
  • POST /api/v1/plugins/capabilities/chat/execute-stream is never issued when the user tries to submit the second message — submit is blocked client-side.
  • No outgoing WS frame {type: "message"} either.

Network/proxy ruled out:

  • Reverse proxy: Caddy v2 (no custom WS config needed for Caddy v2).
  • Direct curl POST /api/v1/plugins/capabilities/chat/execute-stream returns 401 {"detail":"Not authenticated"} instantly — SSE not buffered.
  • WebSocket connections accept and frames pass through (status events arrive).

Conclusion: This is a client-side regression in the packaged Next.js bundle's chat-input state machine. The "responding → idle" state transition is never completed after done arrives, leaving the input/send affordances permanently disabled.

Workaround: drive chat via the deeptutor CLI and read responses from data/user/chat_history.db. RAG, tool calling, sessions all work correctly end-to-end via this path.


Bug 2: Beta 1.4.0b0 has a hardcoded URL string as "not configured" sentinel

Version: deeptutor==1.4.0b0 (PyPI, released 2026-05-21)

Symptom: Frontend immediately errors out on load with:

NEXT_PUBLIC_API_BASE is not configured. Please update data/user/settings/system.json and restart.

Knowledge Bases page shows "No knowledge bases yet" (0). Settings panel doesn't load. No API calls reach the backend.

Root cause (in packaged .next chunks of 1.4.0b0):

A specific URL literal appears to be a developer/staging URL that leaked into the build as a process.env.NEXT_PUBLIC_API_BASE default, and is simultaneously used as a "this value means not-configured" sentinel in the runtime config guard. We discovered this only because our deployment URL happened to collide with that exact literal. The guard logic looks like:

javascript
function(a){
  if(!a || "https://<leaked-dev-url>" === a)
    throw Error("NEXT_PUBLIC_API_BASE is not configured. Please update data/user/settings/system.json and restart.");
  return a;
}("https://<leaked-dev-url>")

Any deployment that legitimately resolves NEXT_PUBLIC_API_BASE to that exact URL hits the guard with a perfectly valid value and the frontend is unusable. This is a build-hygiene issue, not a config bug on the deployer's side — the URL literal is reachable in the public 1.4.0b0 bundle. (Maintainers can locate the exact literal by grepping the 1.4.0b0 chunks for the guard expression above.)

In 1.4.0 final this guard is absent — grep over 1.4.0 chunks returns no match for that comparison expression.

Fix suggestion: Remove the literal-URL sentinel. If a "not-configured" check is still desired, base it on the unsubstituted placeholder marker (__NEXT_PUBLIC_API_BASE_PLACEHOLDER__) which is what _patch_packaged_web_placeholders in deeptutor/runtime/launcher.py is actually designed to replace.


Environment

  • deeptutor from PyPI; packaged Next.js frontend, next-server v16.2.3
  • Reverse proxy: Caddy v2
  • Python 3.11

Versions probed

Version | Released | Chat input bug | URL sentinel bug -- | -- | -- | -- 1.4.0b0 | 2026-05-21 | not tested (sentinel blocks all) | YES 1.4.0 | 2026-05-22 | YES | NO

Related (not part of this report, mentioned for context)

Two non-blocking server-side issues found in 1.4.0 during the same investigation, both with local patches:

  1. A custom LLM provider missing from deeptutor/services/llm/capabilities.py:PROVIDER_CAPABILITIES falls back to DEFAULT_CAPABILITIES (supports_tools: False). Result: tool descriptions are injected into the system prompt instead of passed via OpenAI tools=; the model emits XML <tool_call>...</tool_call> in its reasoning trace, the parser ignores them, and RAG never executes — even though the provider natively returns structured tool_calls. Fix: add the provider entry with supports_tools: True. It may be worth making the fallback behavior more visible (e.g. a warning log when a provider is unknown).
  2. deeptutor/services/rag/service.py:_capture_raw_logs.emit returns an unawaited coroutine when the log emit happens off the event loop, triggering RuntimeWarning: coroutine 'RAGService._emit_tool_event' was never awaited. Suggested fix: schedule via asyncio.ensure_future when a running loop exists; otherwise coro.close() and return.

Happy to send these as separate PRs if useful.

Steps to reproduce

See "Describe the bug" above — symptoms, network observations and reproduction details for both regressions are documented there.

Expected Behavior

Bug 1: chat input field should re-enable after the assistant turn completes, allowing further messages. Bug 2: a valid NEXT_PUBLIC_API_BASE should not be rejected by the config guard.

Related Module

Frontend/Web

Configuration Used

See "Describe the bug" above.

Logs and screenshots

No response

Additional Information

  • DeepTutor Version: 1.4.0 (and 1.4.0b0, see report)
  • Operating System: Linux
  • Python Version: 3.11
  • Node.js Version: next-server v16.2.3 (packaged)
  • Browser: Chrome
  • Reverse proxy: Caddy v2
  • Additional details: see "Describe the bug" above

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions