KeyError
troubleshooting
Python error
machine learning
debugging

Why am I having KeyError 'val_acc'?

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

KeyError: 'val_acc' usually appears when code expects the training history dictionary to contain val_acc, but newer TensorFlow/Keras versions store validation accuracy under val_accuracy. This is a version and metric-name mismatch, not a model-training failure by itself.

The fix is to inspect the keys actually present in history.history and reference metrics dynamically. Hard-coded legacy names from old tutorials often break in modern environments. A small compatibility helper can make plotting and monitoring code robust across versions.

Core Sections

1. Understand where the key comes from

After training, Keras returns a History object:

python
history = model.fit(X_train, y_train, validation_data=(X_val, y_val), epochs=5)
print(history.history.keys())

In current TensorFlow/Keras, common keys include:

  • loss
  • accuracy
  • val_loss
  • val_accuracy

Older examples may reference acc and val_acc, causing KeyError when those keys do not exist.

2. Write version-tolerant metric access

Use fallback logic instead of hard-coded names.

python
1def get_metric(history_dict, preferred, legacy=None):
2    if preferred in history_dict:
3        return history_dict[preferred]
4    if legacy and legacy in history_dict:
5        return history_dict[legacy]
6    raise KeyError(f"Missing both {preferred} and {legacy}")
7
8train_acc = get_metric(history.history, "accuracy", "acc")
9val_acc = get_metric(history.history, "val_accuracy", "val_acc")

This avoids brittle plotting code across environments.

3. Ensure metric is actually configured

If you did not compile with accuracy metrics, validation accuracy keys will never exist.

python
1model.compile(
2    optimizer="adam",
3    loss="sparse_categorical_crossentropy",
4    metrics=["accuracy"]
5)

Then plotting is straightforward:

python
1import matplotlib.pyplot as plt
2
3h = history.history
4plt.plot(h["accuracy"], label="train")
5plt.plot(h["val_accuracy"], label="val")
6plt.legend()
7plt.show()

Also verify callback code, checkpoints, and custom loggers use the same metric names.

Common Pitfalls

  • Copying old tutorial code that references acc/val_acc in modern TensorFlow environments.
  • Forgetting to include metrics=["accuracy"] during compile, so accuracy keys are never logged.
  • Assuming callback monitor names (monitor="val_acc") are version-invariant.
  • Not printing history.history.keys() before plotting/debugging metric access.
  • Mixing standalone keras and tf.keras versions, which can produce inconsistent naming behavior.

Summary

KeyError: 'val_acc' is typically a metric key naming mismatch. Inspect actual history keys, use compatibility fallbacks (val_accuracy vs val_acc), and ensure metrics are configured during compile. Once metric names are aligned across training, callbacks, and plotting, the error disappears and logs remain stable across library upgrades.

In team environments, metric naming drift is often introduced by mixed examples, old notebooks, or partial framework upgrades. A good defensive step is to centralize metric key resolution in one utility module and import that everywhere plots, callbacks, and alerts are configured. Then when names change again in future framework versions, you update one place instead of many scripts. This reduces breakage during upgrades and keeps dashboards consistent.

You can also harden training pipelines by validating metric availability immediately after the first epoch. If required keys are missing, fail fast with an explicit message instead of waiting for a later plotting or checkpoint step to throw an opaque KeyError. For example, after fit, compare expected keys against history.history.keys() and raise a custom exception with remediation guidance. This turns a confusing runtime failure into a clear contract check.

For monitoring systems, prefer explicit callback monitor names tied to your resolved metric key. If your compatibility helper decides on val_accuracy, your early stopping and model checkpoint monitors should use the same resolved value. Keeping training metrics, visualization, and callbacks aligned avoids situations where one component silently tracks a different metric than another. Consistency across these layers is what actually eliminates recurring val_acc errors.

A brief post-upgrade checklist can prevent recurrence: print history keys, verify callback monitor names, and run one plotting smoke test in CI. These checks are cheap and catch metric-name drift before training jobs reach production pipelines.

Make this check part of every dependency upgrade branch.


Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

All Rights Reserved.