Sometimes no response is displayed, even though HTTP 200 is returned

I’m building a lightweight personal chatbot that uses the OpenAI Chat API. The chatbot is embedded into a custom HTML/JS frontend and runs on a PHP backend that sends the prompt and gives back the result using curl_setopt($ch, CURLOPT_WRITEFUNCTION, ...).

It works most of the time — but occasionally (especially on the second or third message), the frontend just hangs. In Chrome DevTools I can see the following:

Status: 200 OK
Response time: <300ms (very fast — suspiciously fast)

But: No text is ever rendered in the chat window

The request body is sent correctly and the request completes — but no chunks are received or displayed.

Here’s the php code, I’m using:

<?php

session_start();
error_reporting(E_ALL);
ini_set('display_errors', 1);
@ini_set('zlib.output_compression', 0);
@ini_set('implicit_flush', 1);
ob_implicit_flush(true);

header('Content-Type: text/plain');
header('Cache-Control: no-cache');
header('Access-Control-Allow-Origin: *');

require_once 'config.php';

$systemPrompt = file_get_contents('prompt.txt');

if (!isset($_SESSION['chat_history'])) {
    $_SESSION['chat_history'] = [
        ["role" => "system", "content" => $systemPrompt]
    ];
}

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $input = json_decode(file_get_contents('php://input'), true);
    $userMessage = trim($input['message'] ?? '');

    if ($userMessage === '') {
        http_response_code(400);
        echo "Leere Eingabe";
        exit;
    }

    $_SESSION['chat_history'][] = ["role" => "user", "content" => $userMessage];

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, "https://api.openai.com/v1/chat/completions");
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, false);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        "Content-Type: application/json",
        "Authorization: Bearer " . OPENAI_API_KEY
    ]);

    $chatPayload = [
        "model" => MODEL,
        "messages" => $_SESSION['chat_history'],
        "temperature" => TEMPERATURE,
        "max_tokens" => MAX_TOKENS,
        "stream" => false
    ];

    $fullReply = '';

    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($chatPayload));

    curl_setopt($ch, CURLOPT_WRITEFUNCTION, function($curl, $data) use (&$fullReply) {
        $lines = explode("n", $data);
        foreach ($lines as $line) {
            if (strpos($line, 'data: ') === 0) {
                $jsonStr = substr($line, 6);
                if (trim($jsonStr) === '[DONE]') break;

                $json = json_decode($jsonStr, true);
                if (isset($json['choices'][0]['delta']['content'])) {
                    $chunk = $json['choices'][0]['delta']['content'];
                    echo $chunk;
                    flush();
                    $fullReply .= $chunk;
                }
            }
        }
        return strlen($data);
    });

    curl_exec($ch);
    curl_close($ch);

    $_SESSION['chat_history'][] = ["role" => "assistant", "content" => $fullReply];

} else {
    http_response_code(405);
    echo "Method not allowed";
}

// Fehlerausgabe, falls nötig
if (isset($ch) && curl_errno($ch)) {
    echo "cURL-Fehler: " . curl_error($ch);
    exit;
}

Does anyone have an idea, why this is happening?

What I’ve ruled out:

  • It’s not an invalid API key — most requests work just fine
  • It’s not a missing prompt.txt — it’s read and logged successfully
  • It’s not a quota issue — no errors from OpenAI, no “insufficient quota”
  • It’s not a general connection problem — the server has internet and cURL works
  • It’s not a JS bug on the first request — only later requests (2nd or 3rd) hang