davila7/claude-code-templates · error

sessionId and message are required

Error message

sessionId and message are required

What it means

HTTP 400 from the claude-api-proxy POST /api/send-message endpoint when the request body lacks sessionId or message (projectPath is optional). It's a plain required-field validation before the proxy attempts to spawn/talk to Claude.

Source

Thrown at cli-tool/src/claude-api-proxy.js:54

  setupRoutes() {
    // Get active conversations/sessions
    this.app.get('/api/sessions', async (req, res) => {
      try {
        const sessions = await this.getActiveSessions();
        res.json({ sessions });
      } catch (error) {
        console.error('Error getting sessions:', error);
        res.status(500).json({ error: error.message });
      }
    });
    
    // Send message to Claude (main endpoint)
    this.app.post('/api/send-message', async (req, res) => {
      try {
        const { sessionId, message, projectPath } = req.body;
        
        if (!sessionId || !message) {
          return res.status(400).json({ error: 'sessionId and message are required' });
        }
        
        const result = await this.sendMessageToClaude(sessionId, message, projectPath);
        res.json(result);
        
      } catch (error) {
        console.error('Error sending message:', error);
        res.status(500).json({ error: error.message });
      }
    });
    
    // Get conversation history
    this.app.get('/api/conversation/:sessionId', async (req, res) => {
      try {
        const { sessionId } = req.params;
        const conversation = await this.getConversationHistory(sessionId);
        res.json({ conversation });
      } catch (error) {

View on GitHub (pinned to a0851ed10c)

Solutions

  1. Ensure the request has header Content-Type: application/json and a body like {"sessionId":"...","message":"..."}
  2. Create a session first (or reuse an existing session id) and include it in the payload
  3. Trim/guard the message field client-side before enabling the send button
  4. Check for accidental typos in field names (session_id vs sessionId)

Example fix

// before
fetch('/api/send-message', { method: 'POST', body: JSON.stringify({ message }) });
// after
fetch('/api/send-message', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ sessionId, message })
});
Defensive patterns

Strategy: validation

Validate before calling

if (!sessionId || !String(message).trim()) throw new Error('missing sessionId or message');
await fetch('/api/send-message', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ sessionId, message: message.trim(), projectPath })
});

Type guard

const isSendPayload = (b) =>
  typeof b?.sessionId === 'string' && b.sessionId.length > 0 &&
  typeof b?.message === 'string' && b.message.trim().length > 0;

Try / catch

catch (e) { if (e.status === 400) disableSendUntilFieldsValid(); else throw e; }

Prevention

When it happens

Trigger: POST /api/send-message with a JSON body missing sessionId, missing message, or with either falsy (empty string / null); also when the body isn't parsed as JSON so both destructure to undefined.

Common situations: Client forgot to create/attach a session id before sending; sending form-encoded or text/plain body to an endpoint that expects req.body JSON (missing content-type: application/json); frontend race where the message input is empty but submit fired.

Related errors


AI-assisted analysis of davila7/claude-code-templates@a0851ed10c (2026-08-28). Data as JSON: /api/errors/ff1af3aabb2efa41. Report an issue: GitHub.