How to Catch and Handle yaml-cpp Parsing Exceptions: A Complete Guide
yaml-cpp throws YAML::ParserException (derived from YAML::Exception) when encountering malformed YAML, providing location metadata via the mark member that you can catch using standard C++ try-catch blocks.
The jbeder/yaml-cpp library converts YAML streams into events or nodes through the YAML::Parser class. When the parser encounters invalid syntax, duplicate anchors, or malformed tags, it raises specific exceptions that carry precise line and column information. Understanding this exception hierarchy allows you to distinguish between parsing errors and representation errors while extracting detailed diagnostic data.
The yaml-cpp Exception Hierarchy
All yaml-cpp exceptions derive from YAML::Exception, which itself inherits from std::runtime_error. This hierarchy is defined in [include/yaml-cpp/exceptions.h](https://github.com/jbeder/yaml-cpp/blob/master/include/yaml-cpp/exceptions.h).
The inheritance chain looks like this:
YAML::Exception ← std::runtime_error
└─ YAML::ParserException ← YAML::Exception
└─ YAML::RepresentationException ← YAML::Exception
├─ InvalidScalar
├─ KeyNotFound / TypedKeyNotFound
├─ BadConversion / TypedBadConversion
├─ BadDereference
├─ BadSubscript
├─ BadPushback
├─ BadInsert
└─ NonUniqueMapKey
YAML::ParserException is thrown during the tokenization and event generation phase. Representation exceptions (like BadConversion or KeyNotFound) occur later when you access or manipulate the resulting YAML::Node objects.
Where Parsing Exceptions Originate
The primary throw point is Parser::HandleNextDocument, declared in [include/yaml-cpp/parser.h](https://github.com/jbeder/yaml-cpp/blob/master/include/yaml-cpp/parser.h) (lines 55-58). When you call YAML::Load or use the streaming operator >>, the library internally invokes this method, which may throw if the input violates the YAML specification.
The concrete exception construction happens in [src/singleparser.cpp](https://github.com/jbeder/yaml-cpp/blob/master/src/singleparser.cpp), where the tokenizer detects invalid tokens. Representation errors are generated in [src/node/node.cpp](https://github.com/jbeder/yaml-cpp/blob/master/src/node/node.cpp) when node access operations fail.
Catching yaml-cpp Exceptions in Practice
You can catch exceptions using either the high-level YAML::Load API or the low-level Parser interface. Both approaches throw the same exception types.
High-Level API with YAML::Load
The YAML::Load function internally constructs a Parser and processes the stream. Wrap this call to catch syntax errors:
#include <fstream>
#include <iostream>
#include <yaml-cpp/yaml.h>
int main() {
std::ifstream fin("config.yaml");
if (!fin) {
std::cerr << "Could not open config.yaml\n";
return 1;
}
try {
// Parser invoked implicitly by the Load function
YAML::Node cfg = YAML::Load(fin);
std::cout << "Version: " << cfg["version"].as<std::string>() << '\n';
}
catch (const YAML::ParserException& ex) {
// Specific handling for syntax errors
std::cerr << "Parsing error: " << ex.what() << '\n';
std::cerr << " at line " << ex.mark.line + 1
<< ", column " << ex.mark.column + 1 << '\n';
return 1;
}
catch (const YAML::Exception& ex) {
// Catches all other yaml-cpp errors (representation, conversion, etc.)
std::cerr << "YAML error: " << ex.what() << '\n';
return 1;
}
catch (const std::exception& ex) {
// Fallback for standard library exceptions
std::cerr << "Unexpected error: " << ex.what() << '\n';
return 1;
}
return 0;
}
Low-Level Parser API
For event-driven parsing, instantiate YAML::Parser directly and call HandleNextDocument:
#include <fstream>
#include <yaml-cpp/parser.h>
#include <yaml-cpp/eventhandler.h>
int main() {
std::ifstream fin("data.yaml");
YAML::Parser parser(fin);
YAML::NodeBuilder builder; // implements EventHandler
try {
while (parser.HandleNextDocument(builder)) {
YAML::Node doc = builder.GetRootNode();
// Process document...
}
}
catch (const YAML::ParserException& e) {
std::cerr << "Parse failure: " << e.what() << '\n';
std::cerr << "Location: line " << e.mark.line + 1 << '\n';
}
}
Accessing Error Location and Messages
Every YAML::Exception contains a YAML::Mark object recording the exact error position. According to the implementation in exceptions.h, the exception message is constructed by Exception::build_what and includes the line and column.
To extract diagnostic information:
e.what(): Returns the complete error message including filename (if available), line, column, and description.e.mark.line: Zero-indexed line number where the error occurred.e.mark.column: Zero-indexed column number.
Since indices are zero-based, add 1 when displaying to users for readability.
Summary
- yaml-cpp throws
YAML::ParserExceptionduring tokenization andYAML::RepresentationExceptionduring node access. - The exception hierarchy is rooted in
YAML::Exception(defined ininclude/yaml-cpp/exceptions.h), allowing you to catch all yaml-cpp errors with a single handler or specialize for specific failure types. - Location data is available via the
markmember, providinglineandcolumnintegers. - Primary throw point is
Parser::HandleNextDocumentininclude/yaml-cpp/parser.h, invoked by both high-levelYAML::Loadand manual parsing loops.
Frequently Asked Questions
What is the base class for all yaml-cpp exceptions?
YAML::Exception is the abstract base class for all yaml-cpp errors, inheriting from std::runtime_error. It is defined in include/yaml-cpp/exceptions.h. Catching this base class will handle ParserException, RepresentationException, and all their derivatives like BadConversion or KeyNotFound.
How do I get the line number where a YAML parsing error occurred?
Access the mark member of the caught exception. This YAML::Mark struct contains line and column members (zero-indexed). For example: ex.mark.line + 1 gives the human-readable line number. This data is populated by the parser in src/singleparser.cpp and propagated through the exception hierarchy.
Should I catch YAML::ParserException or YAML::Exception?
Catch YAML::ParserException if you only need to handle syntax errors (malformed YAML, invalid tags, duplicate anchors). Catch YAML::Exception if you want to handle all yaml-cpp failures including type conversion errors (BadConversion) and missing keys (KeyNotFound). For complete safety, catch YAML::Exception first, then std::exception.
Why does yaml-cpp use exceptions instead of error codes?
The library uses C++ exceptions to separate error handling from normal control flow, consistent with the C++ standard library approach. The Parser class throws ParserException immediately upon detecting invalid tokens in src/singleparser.cpp, preventing invalid state propagation. This design allows you to use RAII for resource cleanup while centralizing error handling in catch blocks.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →