"Cannot modify header information" when writing to file

I would like to use this route to export results from a survey (code slightly shortened, some text replaced by “***”)

<?php

return [
		'routes' => [

			[
				'pattern' => 'intern/export-results',
				'action' => function() {
					
					$list = [];
					
					header::download(['mime'=>'application/csv', 'name' => '***.csv', 'Pragma' => 'no-cache', 'Content-Disposition' => 'attachment']);
					
					$results = site()->index()->find('intern/questions/question-11')->drafts()->sortBy('Surveydate', 'desc');
					
					// Create Header
					$surveydate = "Datum/Zeit";
					$surveyuser = "ID Interviewer";
					$q1 = "Q-1";
					... [more fields here]
					$resultData = array($surveydate, $surveyuser, $q1, $q2, $q3, $q4, $q5, $q6, $q7, $q8, $q9, $q10, $q11);
					array_push($list, $resultData);
					
					// Create Entries
					foreach ($results as $result) {
							$surveydate = $result->surveydate()->toDate('d.m.y, H:i');
							$surveyuser = $result->surveyuser();
							$q1 = $result->q1();
							... [more fields here]
							$resultData = array($surveydate, $surveyuser, $q1, $q2, $q3, $q4, $q5, $q6, $q7, $q8, $q9, $q10, $q11);
							array_push($list, $resultData);
					}
				
					$f = fopen('php://output', 'w');
					
					foreach ($list as $fields) {
						fputcsv($f, $fields, ';', '"');
					}
					
					fpassthru($f);
											
					return new Response('', 'text/plain', 200);
				}
			]

		]
];

I have already used this code on several Kirby 3.x sites with no problems. The new site runs under Kirby 4.1.

All is working well as long as I have approximately 50 records. In a test with 70 records, I get this error:

Whoops\Exception\ErrorException: Cannot modify header information - headers already sent by (output started at /Users/***/Sites/***/site/config/config.php:66) in file /Users/***/Sites/insmed/kirby/src/Http/Response.php on line 290
Stack trace:
  1. Whoops\Exception\ErrorException-&gt;() /Users/tomtom/Sites/insmed/kirby/src/Http/Response.php:290
  2. header() /Users/tomtom/Sites/***/kirby/src/Http/Response.php:290
  3. Kirby\Http\Response-&gt;send() /Users/tomtom/Sites/***/kirby/src/Http/Response.php:98
  4. Kirby\Http\Response-&gt;__toString() /Users/tomtom/Sites/***/index.php:5
  5. require() /Applications/Herd.app/Contents/Resources/valet/server.php:151

I am at a bit at a loss here. The fact that the error only appears after a certain number of records makes me think of a time out problem. Why is there an error regarding the headers?

Any idea very appreciated!

Reverted the site back to Kirby 3.9.7 and don´t get the error.

I’m actually surprised it works in Kirby 3 with any number of record :confused:

The problem seems to be that something wants to set a header after the output has started.
That is probably Kirby which wants to send the “Content-Type: text/plain” header, after you already sent all the content with fputcsv($f, $fields, ';', '"');

I’d suggest changing

to:

					$f = fopen('php://output', 'w');
					
					foreach ($list as $fields) {
						fputcsv($f, $fields, ';', '"');
					}
					
					fclose($f);
					exit;

i am also having problems now with kirby4, with kirby3 my CSV plugin was working fine. any idea why this is happening? the file is written, but at the end i have the ErrorException inside the file. i am doing pretty much the same as you @steenweg. as you said, with less entries it does not happen, but after a certain point it does.

oh, now i got it working after hours of testing xD i had other issues as well so i didnt even try to remove this:


fputcsv($f, $header, ';');
            foreach ($registrations as $registration) {
             fputcsv($f, $registration, ';');
}

fpassthru($f);
//return "END OF EXPORT"; <---- i had to comment this line out. i wanted to finish the file with this text but it seems calling return breaks the file at some point
fclose($f);
exit;

thanks also to @rasteiner, the fclose and exit were helpful as well since again, calling return kinda breaks it.