# Buggy code
def matchyaml(self, file: dict, text: str) -> List[MatchError]:
    matches: List[MatchError] = []
    if not self.matchplay:
        return matches

    yaml = ansiblelint.utils.parse_yaml_linenumbers(text, file["path"])
    # yaml returned can be an AnsibleUnicode (a string) when the yaml
    # file contains a single string. YAML spec allows this but we consider
    # this an fatal error.
    if isinstance(yaml, str):
        return [MatchError(filename=file["path"], rule=LoadingFailureRule())]
    if not yaml:
        return matches

    if isinstance(yaml, dict):
        yaml = [yaml]

    yaml = ansiblelint.skip_utils.append_skipped_rules(yaml, text, file["type"])

    for play in yaml:
        if self.id in play.get("skipped_rules", ()):
            continue

        result = self.matchplay(file, play)
        if not result:
            continue

        if isinstance(result, tuple):
            result = [result]

        if not isinstance(result, list):
            raise TypeError("{} is not a list".format(result))

        for section, message, *optional_linenumber in result:
            linenumber = self._matchplay_linenumber(play, optional_linenumber)
            matches.append(
                self.create_matcherror(
                    message=message,
                    linenumber=linenumber,
                    details=str(section),
                    filename=file["path"],
                )
            )
    return matches


# Traceback (AttributeError)
(venv) user@test:~/ansible$ cat test.yml
- #debug:
#  msg: Hello!

(venv) user@test:~/ansible$ ansible-lint test.yml -vvv
DEBUG    Logging initialized to level 10
DEBUG    Options: Namespace(colored=True, config_file=None, display_relative_path=True, exclude_paths=[], format='plain', listrules=False, listtags=False, parseable=False, parseable_severity=False, playbook=['test.yml'], quiet=False, rulesdir=[], skip_list=[], tags=[], use_default_rules=False, verbosity=3)
DEBUG    Loading rules from /home/user/ansible/venv/lib/python3.8/site-packages/ansiblelint/rules
Traceback (most recent call last):
File "/home/user/ansible/venv/bin/ansible-lint", line 8, in <module>
sys.exit(main())
File "/home/user/ansible/venv/lib/python3.8/site-packages/ansiblelint/__main__.py", line 116, in main
matches.extend(runner.run())
File "/home/user/ansible/venv/lib/python3.8/site-packages/ansiblelint/runner.py", line 73, in run
for child in ansiblelint.utils.find_children(arg, self.playbook_dir):
File "/home/user/ansible/venv/lib/python3.8/site-packages/ansiblelint/utils.py", line 159, in find_children
items = _playbook_items(playbook_ds)
File "/home/user/ansible/venv/lib/python3.8/site-packages/ansiblelint/utils.py", line 134, in _playbook_items
return [item for play in pb_data for item in play.items()]
File "/home/user/ansible/venv/lib/python3.8/site-packages/ansiblelint/utils.py", line 134, in <listcomp>
return [item for play in pb_data for item in play.items()]
AttributeError: 'NoneType' object has no attribute 'items'

# Fixed code
def matchyaml(self, file: dict, text: str) -> List[MatchError]:
    matches: List[MatchError] = []
    if not self.matchplay:
        return matches

    yaml = ansiblelint.utils.parse_yaml_linenumbers(text, file["path"])
    # yaml returned can be an AnsibleUnicode (a string) when the yaml
    # file contains a single string. YAML spec allows this but we consider
    # this an fatal error.
    if isinstance(yaml, str):
        return [MatchError(filename=file["path"], rule=LoadingFailureRule())]
    if not yaml:
        return matches

    if isinstance(yaml, dict):
        yaml = [yaml]

    yaml = ansiblelint.skip_utils.append_skipped_rules(yaml, text, file["type"])

    for play in yaml:
        # Bug #849
        if play is None:
            continue

        if self.id in play.get("skipped_rules", ()):
            continue

        result = self.matchplay(file, play)
        if not result:
            continue

        if isinstance(result, tuple):
            result = [result]

        if not isinstance(result, list):
            raise TypeError("{} is not a list".format(result))

        for section, message, *optional_linenumber in result:
            linenumber = self._matchplay_linenumber(play, optional_linenumber)
            matches.append(
                self.create_matcherror(
                    message=message,
                    linenumber=linenumber,
                    details=str(section),
                    filename=file["path"],
                )
            )
    return matches