Handling File Exceptions and Failed Reads

A missing report needs different handling from denied access

A school report might not exist, might be inaccessible, or might contain invalid text. Treating every failure as an empty report hides important differences.

A file exception reports a failed file operation. Handle the result of the actual operation and distinguish failures by useful categories rather than assuming a prior existence check guarantees success.

  1. Handle absence

    Catch a missing-file failure intentionally.

  2. Preserve causes

    Distinguish permission and decoding problems from absent data.

  3. Avoid races

    Explain why check-then-read is not a guarantee.

Respond to the actual read outcome

  1. Read request

    Try the operation the task needs.

    Open report
  2. Outcome

    The operation succeeds or reports its failure.

    Text or error
  3. Policy

    Recover only when the cause is understood.

    Prompt, retry or propagate
Read these stages alongside the complete example. They explain the relationship; they do not execute code.

An earlier check can become stale

A file can disappear or permissions can change between checking existence and opening it. Attempt the operation and handle its result rather than relying only on a preliminary check.

Missing data may allow a user prompt; permission failure may require access correction; damaged encoding may need file repair. Broadly swallowing all exceptions confuses these cases and can mask programming errors.

Before starting, review handling known failure categories. These examples use JavaScript; other languages can use different syntax and rules.

Handle a real missing file in Python

Run this Python 3 program in a newly created empty exercise directory. It reads an intentionally absent path and catches FileNotFoundError.

try:
    with open('missing-report.txt', 'r', encoding='utf-8') as file:
        print(file.read())
except FileNotFoundError:
    print('Report not found')

Expected output: Report not found. Other exception categories are not relabeled as a missing report. If the file exists, the premise changes and the read may succeed.

Model a missing operation locally

This JavaScript Map model throws a deliberate error when its key is absent. It does not simulate the operating system’s permissions, concurrent changes or real error codes.

The catch prints the known missing-message outcome. Real handling should use the file API’s categories, as in the Python example above.

JavaScript · local teaching example

const modelFiles = new Map();
try {
  if (!modelFiles.has('report.txt')) throw new Error('Report not found');
  console.log(modelFiles.get('report.txt'));
} catch (error) {
  console.log(error.message);
}

Expected output

Report not found

A file can exist but fail text decoding

This complete Python 3 program creates an exercise file containing a byte that is not valid on its own in UTF-8. The read fails during decoding, not because the path is missing.

with open('invalid.txt', 'wb') as file:
    file.write(bytes([255]))
try:
    with open('invalid.txt', 'r', encoding='utf-8') as file:
        print(file.read())
except UnicodeDecodeError:
    print('Report encoding is invalid')

Expected output: Report encoding is invalid. Replacing bad characters is a possible policy, but it can lose information and should not happen accidentally.

Apply the rule to a small change

Put a report in the local model before reading. Keep the same missing check and predict the successful output.

Worked answer

The key exists, so no error is thrown and Maya: 75 is displayed. Testing both success and absence confirms that the handler does not always replace the operation with a fallback.

JavaScript · local teaching example

const modelFiles = new Map([['report.txt', 'Maya: 75']]);
try {
  if (!modelFiles.has('report.txt')) throw new Error('Report not found');
  console.log(modelFiles.get('report.txt'));
} catch (error) {
  console.log(error.message);
}

Expected output

Maya: 75

Recognize mistakes and limits

A failure can occur after partial work. Repeating a write blindly can duplicate appended records, while replacement can lose data. Decide whether retries are safe for that operation.

Do not automatically delete or recreate a file on every read failure. Preserve the relevant cause and avoid exposing private content in logs. Distinguish recovery from merely suppressing the exception.

For the language or tool rules used here, see Python file modes and encodings.

Check the core idea

Why is an existence check before a read insufficient as a guarantee?
Choose one answer. You can try again.

Answer and explanation

The filesystem can change between the check and the read.

Yes. Handle the actual operation result.

Apply the idea to a new situation

Should a UTF-8 decoding error be reported as “file missing”?
Choose one answer. You can try again.

Answer and explanation

No; the file exists but its bytes do not match the chosen decoding rules.

Yes. Preserve the specific failure meaning.

Recover from the cause, not from a vague failure label

Attempt the required operation, handle meaningful categories and keep unexpected failures visible. Missing paths, permission problems and invalid formats imply different responses.

Connect this idea with useful error identities and write modes and retry consequences.

Reaching the recap and completing the quizzes are separate milestones.

    Next lesson: File Paths: Relative, Absolute and Resolved Locations →