Problem/Motivation

When PHP returns an error during a file upload attempt (see http://php.net/manual/features.file-upload.errors.php), an error message with details potentially about the server configuration are displayed to the user. These file upload errors should be logged instead and a generic message displayed to the user.

Original problem/motivation:

When PHP throws UPLOAD_ERR_NO_TMP_DIR error while uploading a file, function file_check_upload($source = 'upload') won't handle it correctly. in fact this function will quit leaving user with cryptic error message An unknown error has occurred. The error is known, however no one bothered to write separate handler for it.

Steps to reproduce

Proposed resolution

1. Check for the following errors:

  • UPLOAD_ERR_FORM_SIZE: "The file $original_file_name could not be saved because it exceeds " . format_size(Environment::getUploadMaxSize()) . ", the maximum allowed size for uploads.";
  • UPLOAD_ERR_NO_FILE: "The file $original_file_name could not be saved because the upload did not complete.";
  • UPLOAD_ERR_NO_TMP_DIR: "The file $original_file_name could not be saved because the server is missing a temporary folder.";
  • UPLOAD_ERR_CANT_WRITE: "The file $original_file_name could not be saved because the server is unable to write to disk.";
  • UPLOAD_ERR_EXTENSION: "The file $original_file_name could not be saved because a PHP extension stopped the file upload. PHP does not provide a way to ascertain which extension caused the file upload to stop; examining the list of loaded extensions with phpinfo() may help.";

2. Present an unconditional user-facing error that doesn't divulge any specifics that might divulge information about the server and be a security risk: \Drupal::messenger()->addError(t('The file %file could not be saved. A server error has occurred.', ['%file' => $original_file_name]));

Remaining tasks

Needs tests
Agree on the text of the error messages
Review
Commit

User interface changes

API changes

Data model changes

Release notes snippet

Beta phase evaluation

Reference: https://www.drupal.org/core/beta-changes
Issue category Bug because the file_save_upload is ignoring detailed errors and reporting a generic one under certain conditions
Unfrozen changes Unfrozen because it only changes file saving error reporting to be more detailed
Prioritized changes The main goal of this issue is sys-admin sanity when encountering server errors
CommentFileSizeAuthor
#82 92944-82.patch8.05 KBsmavri
#81 reroll_diff_75-77.txt3 KBravi.shankar
#77 92944-77.patch8 KBkostyashupenko
#76 After-NoTmpDir-log.png5.74 KBquietone
#76 After-NoTmpDir.png9.29 KBquietone
#75 reroll_diff_69_75.txt12.23 KBmohit_aghera
#75 92944-75.patch7.93 KBmohit_aghera
#69 interdiff-92944-64-69.txt1.69 KBmohit_aghera
#69 92944-69.patch6.96 KBmohit_aghera
#64 interdiff_61-64.txt1.82 KBvsujeetkumar
#64 92944-64.patch6.97 KBvsujeetkumar
#61 interdiff-58-61.txt1.67 KBmstrelan
#61 92944-61.patch6.97 KBmstrelan
#58 92944-58.patch6.8 KBquietone
#58 interdiff-56-58.txt1.76 KBquietone
#56 92944-56.patch6.78 KBquietone
#56 interdiff-54-56.txt7.4 KBquietone
#54 92944-54.patch6.16 KBquietone
#54 interdiff-49-54.txt4.76 KBquietone
#53 92944-53.patch5.92 KBquietone
#53 interdiff-49-53.txt4.51 KBquietone
#49 interdiff_48-49.txt1.47 KBvsujeetkumar
#49 upload-error-handling-92944-49.patch2.78 KBvsujeetkumar
#48 upload-error-handling-92944-48.patch2.79 KBvsujeetkumar
#46 interdiff_44_46.txt2.26 KBanmolgoyal74
#46 upload-error-handling-92944-46.patch2.82 KBanmolgoyal74
#44 upload-error-handling-92944-44.patch2.93 KBanmolgoyal74
#43 interdiff_36_43.txt5.53 KBanmolgoyal74
#43 upload-error-handling-92944-43.patch2.98 KBanmolgoyal74
#36 upload-error-handling-92944-36.patch3.16 KBPavan B S
#25 upload-error-handling-92944-25.patch2.99 KBDavid_Rothstein
#16 interdiff.txt874 bytesjhedstrom
#16 upload-error-handling-92944-16.patch1.35 KBjhedstrom
#9 add-better-php-error-handling-92944-9.patch969 bytesSiliconMind

Issue fork drupal-92944

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

killes@www.drop.org’s picture

Status: Needs work » Active

no patch

gregmac’s picture

Version: 4.7.4 » 5.2

This seems to still be the case in 5.2.

Patch, based on above code:

--- includes/file.inc.orig        2007-05-31 01:48:58.000000000 -0400
+++ includes/file.inc  2007-09-26 01:50:43.000000000 -0400
@@ -192,6 +192,11 @@
     return $upload_cache[$source];
   }

+  if ($_FILES["files"]["error"][$source] && $_FILES["files"]["error"][$source] == UPLOAD_ERR_NO_TMP_DIR) {
+    drupal_set_message(t('The file %file could not be saved, because no server temp folder exists.', array('%file' => $_FILES["files"]["name"][$source])), 'error');
+    return FALSE;
+  }
+
   // If a file was uploaded, process it.
   if ($_FILES["files"]["name"][$source] && is_uploaded_file($_FILES["files"]["tmp_name"][$source])) {

gregmac’s picture

Status: Active » Needs review
StevenPatz’s picture

Status: Needs review » Active

No patch.

dpearcefl’s picture

Status: Active » Closed (won't fix)

Due to the age of the last comment on this issue and due to the fact that D5 is no longer supported, I am closing this issue.

dpearcefl’s picture

Status: Closed (won't fix) » Postponed

Going to open this issue until I can confirm it doesn't exist in modern Drupal.

SiliconMind’s picture

Version: 5.2 » 8.x-dev

Since D6 the UPLOAD_ERR_NO_TMP_DIR is catched as "general" error and users get message: "The file %file could not be saved. An unknown error has occurred." Such a message is not helpful at all :( I Don't get it, PHP defines only 7 possible errors with file upload - it's not that hard to set messages appropriate for each one of these: http://php.net/manual/en/features.file-upload.errors.php

SiliconMind’s picture

Issue summary: View changes
Status: Postponed » Needs review
FileSize
969 bytes

After over 5 years, a patch. Finally! :)
Also added case for UPLOAD_ERR_CANT_WRITE error.

StevenPatz’s picture

I can test this, this weekend.

jhedstrom’s picture

Issue summary: View changes
Status: Needs review » Reviewed & tested by the community

Patch still applies, and provides more detailed feedback when such errors occur.

I think due to the procedural nature of file_save_upload(), writing a test for these two errors would be quite difficult. If/when we ever switch to use the Symfony file validators, they provide complete coverage of these errors (as unit tests).

I've updated the issue summary to include a beta phase evaluation.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 9: add-better-php-error-handling-92944-9.patch, failed testing.

Status: Needs work » Needs review
jhedstrom’s picture

Status: Needs review » Reviewed & tested by the community

Back to RTBC. Not sure what's going on with the testbot today.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work

If we are doing this we should make this complete there's now UPLOAD_ERR_EXTENSION see http://php.net/manual/en/features.file-upload.errors.php

I agree that testing this is going to be unnecessarily tricky.

jhedstrom’s picture

Status: Needs work » Needs review
FileSize
1.35 KB
874 bytes

This adds UPLOAD_ERR_EXTENSION. I took the error text directly from the php manual.

swentel’s picture

Status: Needs review » Reviewed & tested by the community

Oh yes, I've been bitten by this one a couple of times already.

catch’s picture

Status: Reviewed & tested by the community » Fixed

Committed/pushed to 8.0.x, thanks!

  • catch committed 1cb897d on 8.0.x
    Issue #92944 by jhedstrom, SiliconMind: Drupal won't report file upload...
David_Rothstein’s picture

Title: Drupal won't report file upload error when UPLOAD_ERR_NO_TMP_DIR occurs » (rollback) Drupal won't report file upload error when UPLOAD_ERR_NO_TMP_DIR occurs
Status: Fixed » Needs work
+ drupal_set_message(t('The file %file could not be saved because server is missing a temporary folder.', array('%file' => $file_info->getFilename())), 'error');
+ drupal_set_message(t('The file %file could not be saved because server is unable to write to disk.', array('%file' => $file_info->getFilename())), 'error');
+ drupal_set_message(t('The file %file could not be saved because a PHP extension stopped the file upload. PHP does not provide a way to ascertain which extension caused the file upload to stop; examining the list of loaded extensions with phpinfo() may help.', array('%file' => $file_info->getFilename())), 'error');

These technical details should not be shown to end users; 99% won't understand what it means and can't do anything to fix it. It might even be considered a small security flaw, since it exposes information about how the server is configured.

These could perhaps be watchdog messages instead, with the end-user-facing message changed from "unknown error" to "server error" or similar...

But first I think this should be rolled back because it causes more problems than it solves.

David_Rothstein’s picture

Title: (rollback) Drupal won't report file upload error when UPLOAD_ERR_NO_TMP_DIR occurs » (rollback) Drupal reports an "unknown" file upload error even when a known error, such as UPLOAD_ERR_NO_TMP_DIR, occurs
Issue tags: +Needs backport to D7

More accurate title, also. And we can probably backport at least some of this (e.g. watchdog messages).

  • catch committed 1ad3433 on 8.0.x
    Revert "Issue #92944 by jhedstrom, SiliconMind: Drupal won't report file...
catch’s picture

That's a good point. Reverted the commit.

What about changing these errors to a trigger_error() so it shows up both on screen depending on error reporting levels and in watchdog. Then the more restricted message with dsm() sounds good.

catch’s picture

Title: (rollback) Drupal reports an "unknown" file upload error even when a known error, such as UPLOAD_ERR_NO_TMP_DIR, occurs » Drupal reports an "unknown" file upload error even when a known error, such as UPLOAD_ERR_NO_TMP_DIR, occurs
David_Rothstein’s picture

Status: Needs work » Needs review
FileSize
2.99 KB

Hm, I think trigger_error() makes sense, although while trying that I found that the triggered error usually won't be displayed even if it's configured to (since file uploads usually happen via Ajax and Drupal only displays errors to the screen during Ajax if they're fatal, which usually makes sense but in this case seems like a bug).

I also wasn't sure how to handle translation here - do we not run through t() since the primary destination is watchdog or do we translate since it might appear on the screen?

Here's a patch that tries trigger_error() anyway. I also fixed a grammar issue in a couple of the messages ("because server" => "because the server").

David_Rothstein’s picture

...I found that the triggered error usually won't be displayed even if it's configured to (since file uploads usually happen via Ajax and Drupal only displays errors to the screen during Ajax if they're fatal, which usually makes sense but in this case seems like a bug).

Eventually decided that this really seems like a bug - filed #2400477: Drupal never displays non-fatal error messages to the screen during Ajax requests

jhedstrom’s picture

I think the patch in #25 is good to go, but should it perhaps wait on #2400477: Drupal never displays non-fatal error messages to the screen during Ajax requests?

  • catch committed 1ad3433 on 8.1.x
    Revert "Issue #92944 by jhedstrom, SiliconMind: Drupal won't report file...
  • catch committed 1cb897d on 8.1.x
    Issue #92944 by jhedstrom, SiliconMind: Drupal won't report file upload...

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

  • catch committed 1ad3433 on 8.3.x
    Revert "Issue #92944 by jhedstrom, SiliconMind: Drupal won't report file...
  • catch committed 1cb897d on 8.3.x
    Issue #92944 by jhedstrom, SiliconMind: Drupal won't report file upload...

  • catch committed 1ad3433 on 8.3.x
    Revert "Issue #92944 by jhedstrom, SiliconMind: Drupal won't report file...
  • catch committed 1cb897d on 8.3.x
    Issue #92944 by jhedstrom, SiliconMind: Drupal won't report file upload...

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

  • catch committed 1ad3433 on 8.4.x
    Revert "Issue #92944 by jhedstrom, SiliconMind: Drupal won't report file...
  • catch committed 1cb897d on 8.4.x
    Issue #92944 by jhedstrom, SiliconMind: Drupal won't report file upload...

  • catch committed 1ad3433 on 8.4.x
    Revert "Issue #92944 by jhedstrom, SiliconMind: Drupal won't report file...
  • catch committed 1cb897d on 8.4.x
    Issue #92944 by jhedstrom, SiliconMind: Drupal won't report file upload...

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Pavan B S’s picture

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

mvonfrie’s picture

Can you reroll patch #36 for Drupal 8.9 and 9.x, please?

anmolgoyal74’s picture

anmolgoyal74’s picture

alexpott’s picture

Status: Needs review » Needs work
  1. +++ b/core/modules/file/file.module
    @@ -976,6 +977,18 @@ function _file_save_upload_single(\SplFileInfo $file_info, $form_field_name, $va
    +      $error_to_log = t('The file %file could not be saved because the server is missing a temporary folder.', ['%file' => $file_info->getFilename()]);
    ...
    +      $error_to_log = t('The file %file could not be saved because the server is unable to write to disk.', ['%file' => $file_info->getFilename()]);
    ...
    +      $error_to_log = t('The file %file could not be saved because a PHP extension stopped the file upload. PHP does not provide a way to ascertain which extension caused the file upload to stop; examining the list of loaded extensions with phpinfo() may help.', ['%file' => $file_info->getFilename()]);
    
    @@ -985,11 +998,21 @@ function _file_save_upload_single(\SplFileInfo $file_info, $form_field_name, $va
    +      $error_to_log = t('The file %file could not be saved. An unknown error has occurred.', array('%file' => $file_info->getFilename()));
    

    Log messages are not translated.

  2. +++ b/core/modules/file/file.module
    @@ -985,11 +998,21 @@ function _file_save_upload_single(\SplFileInfo $file_info, $form_field_name, $va
    +    $files[$i] = FALSE;
    

    This needs to return FALSE here.

  3. +++ b/core/modules/file/file.module
    @@ -985,11 +998,21 @@ function _file_save_upload_single(\SplFileInfo $file_info, $form_field_name, $va
    -  // Begin building file entity.
    +
    

    This line shouldn't be removed.

anmolgoyal74’s picture

Status: Needs work » Needs review
FileSize
2.82 KB
2.26 KB

Addressed #45.

quietone’s picture

Version: 8.9.x-dev » 9.2.x-dev
Status: Needs review » Needs work
Issue tags: +Needs tests, +Needs issue summary update

This needs to be on 9.2.x and it needs a reroll. Needs IS update - at least have the proposed resolution and the remaining tasks to make it easier to find out what needs to be done here.

vsujeetkumar’s picture

Status: Needs work » Needs review
FileSize
2.79 KB

Reroll patch given for 9.2.x.

vsujeetkumar’s picture

Fixing some phpcs issues. Please have a look.

quietone’s picture

Status: Needs review » Needs work
  • +++ b/core/modules/file/file.module
    @@ -943,6 +944,18 @@ function _file_save_upload_single(\SplFileInfo $file_info, $form_field_name, $va
    +      $error_to_log = 'The file %file could not be saved because the server is missing a temporary folder.';
    

    This won't display the file name.

  • +++ b/core/modules/file/file.module
    @@ -943,6 +944,18 @@ function _file_save_upload_single(\SplFileInfo $file_info, $form_field_name, $va
    +      $error_to_log = 'The file ' . $file_info->getFilename() . ' could not be saved because the server is unable to write to disk.';
    

    This is displaying the temporary file name. Should be $original_file_name.

    There is at least one other instance to change.

  • How to write the test when this triggers and error?

    I also think this needs a screenshot of the screen output when one of the newly detected errors occurs. If you make a screenshot - put it in the IS. Thx.

    Version: 9.2.x-dev » 9.3.x-dev

    Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

    quietone’s picture

    Issue summary: View changes
    Issue tags: -Needs issue summary update
    quietone’s picture

    Status: Needs work » Needs review
    Issue tags: -Needs tests
    FileSize
    4.51 KB
    5.92 KB

    Adding tests and implemented fixes for #50.

    quietone’s picture

    Ignore that, forgot to run commit-code-check.

    Status: Needs review » Needs work

    The last submitted patch, 54: 92944-54.patch, failed testing. View results

    quietone’s picture

    Title: Drupal reports an "unknown" file upload error even when a known error, such as UPLOAD_ERR_NO_TMP_DIR, occurs » Display generic msg and log detailed message when file upload fails
    Status: Needs work » Needs review
    FileSize
    7.4 KB
    6.78 KB

    More or less started over. This attempts to properly display a message to the user and log an useful, more detailed message. The test has been updated to check both messages.

    Update title to what this is doing.

    Status: Needs review » Needs work

    The last submitted patch, 56: 92944-56.patch, failed testing. View results

    quietone’s picture

    Status: Needs work » Needs review
    FileSize
    1.76 KB
    6.8 KB

    OK. Let's get the max upload size differently.

    quietone’s picture

    Issue tags: +Bug Smash Initiative
    fubarhouse’s picture

    Issue tags: +DrupalSouth

    Read the code, all seems logical.
    Looks like a very positive change to have.

    I'm afraid I couldn't apply the patch to 9.3.x - any extra information could be useful to apply the patch here.
    Else-wise it's line 17 on the Kernel test file which it's failing at.

    mstrelan’s picture

    The patch appears to be against 9.2.x, have rerolled against 9.3.x and added keys to the dataProvider to make it easier to see what (if anything) fails.

    fubarhouse’s picture

    Excellent. The re-roll worked @mstrelan.
    Looks great, applies cleanly.

    Kristen Pol’s picture

    Status: Needs review » Needs work

    Thanks for the updated patch. Here's some feedback:

    1. +++ b/core/modules/file/file.module
      @@ -957,9 +970,17 @@ function _file_save_upload_single(\SplFileInfo $file_info, $form_field_name, $va
      -      \Drupal::messenger()->addError(t('The file %file could not be saved. An unknown error has occurred.', ['%file' => $original_file_name]));
      -      return FALSE;
      -
      +      $error_to_log = 'The file ' . $file_info->getFilename() . ' could not be saved. An unknown error has occurred.';
      

      Should use $original_file_name instead of $file_info->getFilename().

    2. +++ b/core/modules/file/file.module
      @@ -957,9 +970,17 @@ function _file_save_upload_single(\SplFileInfo $file_info, $form_field_name, $va
      +    // problems that end users should not know about (and cannot fix by
      +    // attempting the upload again).
      

      Nitpick: IMO the parentheses in the comment are unnecessary.

    3. +++ b/core/modules/file/tests/src/Kernel/FileModuleTest.php
      @@ -17,21 +17,80 @@ class FileModuleTest extends KernelTestBase {
      +    $expected_message = new TranslatableMarkup("The file %file could not be saved. An unknown error has occurred.", ['%file' => $file_name]);
      

      Nitpick: Should be single quotes rather than double.

    vsujeetkumar’s picture

    Status: Needs work » Needs review
    FileSize
    6.97 KB
    1.82 KB

    Addressed #63.1, 63.2 and 63.3, Please have a look.

    quietone’s picture

    Issue summary: View changes

    This looks good to me but I can't RTBC.

    kim.pepper’s picture

    Status: Needs review » Needs work
    Issue tags: +Needs issue summary update

    The issue summary might need an update:

    check for the following errors and show a useful error message

    However, we have only changed the message that gets logged, the message that is presented to the user is still:

    +++ b/core/modules/file/file.module
    @@ -957,9 +970,17 @@ function _file_save_upload_single(\SplFileInfo $file_info, $form_field_name, $va
    +    \Drupal::messenger()->addError(t('The file %file could not be saved. An unknown error has occurred.', ['%file' => $original_file_name]));
    

    .

    mstrelan’s picture

    Title: Display generic msg and log detailed message when file upload fails » Display generic message and log detailed message when file upload fails
    Amber Himes Matz’s picture

    Issue summary: View changes

    1. For the message that is presented to the user, instead of "an unknown error", what about "a server error" and indicate that the details have been logged? (Suggested a long long time ago in #20.)

    +++ b/core/modules/file/file.module
    @@ -957,9 +970,17 @@ function _file_save_upload_single(\SplFileInfo $file_info, $form_field_name, $va
    +    \Drupal::messenger()->addError(t('The file %file could not be saved due to a server error. Error details have been logged.', ['%file' => $original_file_name]));
    

    2. Also, I updated the issue summary about the user-facing error message. (Perhaps could still use an IS update about steps to reproduce?)

    mohit_aghera’s picture

    Status: Needs work » Needs review
    Issue tags: -Needs issue summary update
    FileSize
    6.96 KB
    1.69 KB

    @kim.pepper
    As per the comment in #20, we can skip the updating user facing message.

    @Amber Himes Matz
    I've updated the patch and test with the message The file %file could not be saved. A server error has occurred.
    Do you think we need to get approval from UX team as well or we are good?

    Amber Himes Matz’s picture

    Issue tags: +Needs usability review
    +++ b/core/modules/file/file.module
    @@ -957,9 +970,17 @@ function _file_save_upload_single(\SplFileInfo $file_info, $form_field_name, $va
    +    \Drupal::messenger()->addError(t('The file %file could not be saved. A server error has occurred.', ['%file' => $original_file_name]));
    

    Looks like here is where the generic user message is constructed. Thank you @mohit_aghera for the update.

    Yes, though minor, I do think it's a good idea for the UX team to have a look. So I'll add a tag.

    Amber Himes Matz’s picture

    I'm going to try to reproduce one of the errors and add a screenshot of the user-facing error message for the benefit of the usability review.

    Amber Himes Matz’s picture

    Title: Display generic message and log detailed message when file upload fails » Display generic message and log detailed message when file upload fails due to PHP error
    Issue summary: View changes
    Status: Needs review » Needs work
    Issue tags: -Needs usability review +Needs steps to reproduce, +Needs screenshots

    Updated title, since this issue is specific to error messages that PHP returns, not errors about file field configuration. (See http://php.net/manual/features.file-upload.errors.php.)

    Updated issue summary, per comments that indicated that $original_file_name should be used and not $file_info->getFilename(). Also added the missing cases to the IS. And updated point 2 about the user-facing message contents.

    So, in my attempt to reproduce a PHP file upload error, I updated my local site's PHP ini with the following values:

    upload_tmp_dir = "/monkey"
    upload_max_filesize = 10
    

    I added a File field to the Article content type with the defaults, and the help text does show a file size limit of 10 bytes, as set in my INI file, with a file type limit of ".txt".

    I then tried to upload INSTALL.txt (94 bytes) to a new article. This is what happened:

    1. No error was displayed by AJAX when I uploaded the file. The file name value remained in the field.
    2. No error was displayed in the messages block and the file was successfully saved, albeit without a file upload attached. (The file upload error was essentially silent.)
    3. The error message was logged as follows:

    Type 	file
    Date 	Friday, September 24, 2021 - 15:46
    User 	admin
    Location 	https://92944-fileuploaderrmsg.ddev.site/node/add/article?_wrapper_format=drupal_ajax&ajax_form=1&element_parents=field_file%2Fwidget%2F0
    Referrer 	https://92944-fileuploaderrmsg.ddev.site/node/add/article
    Message 	The file INSTALL.txt could not be saved because it exceeds 10 bytes, the maximum allowed size for uploads.
    Severity 	Error
    

    So, I am not convinced that the if (isset($error_to_log)) block on lines 973-982 in core/modules/file.module are running "unconditionally". As, what is supposed to happen is that a helpful technical message is logged AND a generic helpful-but-not-detailed-and-not-unknown error message is shown to the user.

    I am also not sure if this is something to do with AJAX and we're in the wrong file. I'm also not sure if there is a server configuration or permissions issue that prevents this type of PHP error message from being displayed. I tried turning display_errors =1 in my ini file, and I tested the file upload with admin, content editor, and limited editor users.

    quietone’s picture

    The changes here are in a function that is now deprecated. It was deprecated in #3232248: Move _file_save_upload_single to a service and deprecate. Perhaps the work here should be in function file_save_upload()?

    alexpott’s picture

    @quietone++ the work he should definitely only change file_save_upload(). It shouldn't touch the new FileUploadHandler service.

    mohit_aghera’s picture

    Status: Needs work » Needs review
    FileSize
    7.93 KB
    12.23 KB

    @quietone @alexpott
    I've refactored the code and moved all the logic to "file_save_upload()" method.
    I had to re-roll the patch as well because we renamed test cases classes. Added re-roll diff file as well.
    I've added new test cases instead of modifying existing one to keep things simple.

    quietone’s picture

    Issue summary: View changes
    Status: Needs review » Needs work
    FileSize
    9.29 KB
    5.74 KB

    @mohit_aghera, thanks for updating the patch. Unfortunately, the patch no longer applies but it was just the changes to the test so I went ahead and did some manual testing.

    To generate a On the webserver I moved /tmp to /tmp.bkp and then uploaded a file. That resulted in the same message displayed to the user and in the logs.

    UI

    Logged

    The message logged and the message displayed are supposed to be different. The user can't do anything about the server so they don't need to know the details. This agrees with what Amber Himes Matz said #72 "As, what is supposed to happen is that a helpful technical message is logged AND a generic helpful-but-not-detailed-and-not-unknown error message is shown to the user.'

    Do we have agreement on the text of the generic message that is shown to the user? What is in the IS is not in the patch.

    kostyashupenko’s picture

    Rerolled against 9.3.x

    @quietone don't hesitate to add "Needs reroll" tag next time)

    Status: Needs review » Needs work

    The last submitted patch, 77: 92944-77.patch, failed testing. View results

    Version: 9.3.x-dev » 9.4.x-dev

    Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

    quietone’s picture

    Version: 9.4.x-dev » 10.0.x-dev

    @kostyashupenko, just a reminder to always and an interdiff or diff when rerolling a patch. And I did not add the tag because this needs more work than a reroll.

    This needs work for #76 and a diff between the patches in #75 and #77.

    ravi.shankar’s picture

    FileSize
    3 KB

    Added reroll diff of patch #75 and #77.

    smavri’s picture

    Here is a patch for 9.4

    mstrelan’s picture

    Version: 10.0.x-dev » 11.x-dev

    I attempted to re-roll for 11.x and convert this to an MR but it proved difficult due to changes in #3375447: Create an UploadedFile validator and deprecate error checking methods on UploadedFileInterface. I wondered if this issue is still relevant but it is lacking steps to reproduce.

    catch’s picture

    I looked at the diff in https://git.drupalcode.org/project/drupal/-/commit/6bd3ad841f346d650ace3... and I also can't tell what's left here.

    ::handleFileUpload() creates violations, these are then formatted into a messenger message here: https://git.drupalcode.org/project/drupal/-/commit/6bd3ad841f346d650ace3...

    The issue summary is saying that instead of listing the errors, we should log them. The errors we list now are validation constraints, not the raw message, so I think that's fine.

    However, it looks like whereas we used to cover UPLOAD_ERR_NO_TMP_DIR as an explicit case in FileUploadHandler::handleFileUpload() https://git.drupalcode.org/project/drupal/-/commit/6bd3ad841f346d650ace3... that wasn't handled in the new code, and I can't see anywhere else in core that it's handled. Symfony's FileValidator does handle it explicitly but I don't think we're using that.

    Given all that, if the above is correct, which I'm not 100% sure it is, then I think what we're missing is logging the full range of errors we used to throw exceptions for, but now only show a handful of violation messages for.

    catch’s picture

    I just committed #2838474: Remove dependency of "file_system" service on "logger" which I'm not sure directly affects this issue but might influence the eventual outcome even if it doesn't.

    kim.pepper’s picture

    I believe it's because of how we move uploaded files.

    We call \Drupal\Core\File\FileSystem::moveUploadedFile() which calls \move_uploaded_file(). We don't call \Symfony\Component\HttpFoundation\File\UploadedFile::move() which would throw those exceptions. From looking at the comments, due to a lack of stream wrapper support.

    kim.pepper’s picture

    We could add those missing validations to \Drupal\file\Validation\Constraint\UploadedFileConstraintValidator::validate(), I'm just not sure if they are triggered before we try and move the file.

    kim.pepper’s picture

    Category: Bug report » Task

    We are catching UPLOAD_ERR_NO_TMP_DIR in https://git.drupalcode.org/project/drupal/-/blob/11.x/core/modules/file/...

          default => $this->context->buildViolation($constraint->uploadErrorMessage, [
            '%file' => $value->getClientOriginalName(),
          ])->setCode((string) $value->getError())
            ->addViolation()
    

    This means this issue is about adding additional logging to file_save_upload() which would reclassify it as a task, IMO.