"Snakeyaml error handling is tough"

Cassandra for years has relied on snakeyaml to parse configuration files, and it does a fine job, really not a lot of complaints. Until one day a colleague of mine discovered an issue where a permission issue incorrectly reported as an invalid yaml file (complete with the supposedly offending key). Digging into the source code and trying to match up the message. I found that we were handling YAMLException

        Yaml yaml = new Yaml(constructor);
        Config result = loadConfig(yaml, configBytes);
        return result;
catch (YAMLException e)
        throw new ConfigurationException("Invalid yaml: " + url + SystemUtils.LINE_SEPARATOR
                                             +  " Error: " + e.getMessage(), false);

Which is effectively calling loadAs from snakeyaml

private Config loadConfig(Yaml yaml, byte[] configBytes)
        Config config = yaml.loadAs(new ByteArrayInputStream(configBytes), Config.class);
        // If the configuration file is empty yaml will return null. In this case we should use the default
        // configuration to avoid hitting a NPE at a later stage.
        return config == null ? new Config() : config;

So for this particular version I hunted down the release of snakeyaml as 1.12 and digging into the source I find load as uses StreamReader to wrap the stream passed into loadAs

public <T> T loadAs(Reader io, Class<T> type) {
    return (T) loadFromReader(new StreamReader(io), type);

A new StreamReader is called, which in the source calls this.update

public StreamReader(Reader reader) { = "'reader'";
        this.buffer = ""; = reader;
        this.eof = false; = new char[1024];

Unfortunately, “this.update” handles IOException by throwing a new YAMLException. So this is how we turn a permission error into an invalid YAML

} catch (IOException ioe) {
        throw new YAMLException(ioe);


Just watch out for invalid yaml errors when using Cassandra (or anything consuming snakeyaml) it may not actually be what you think it is.