Skip to content

error handling issue: cloud-init produces a traceback on invalid user configuration #7006

Description

@cnslynch

Bug report

_maybe_set_hostname() in cloudinit/cmd/main.py calls util.get_hostname_fqdn(init.cfg, cloud, metadata_only=True) before entering its only try/except block (that block guards just the later cc_set_hostname.handle(...) call). get_hostname_fqdn() in cloudinit/util.py then does if "hostname" in cfg and cfg["hostname"].find(".") > 0: with no type check or str() cast on cfg["hostname"]. If the merged config's hostname value is ever a non-string (e.g. an all-digit value that gets interpreted as an int somewhere upstream instead of staying a string), this raises AttributeError: 'int' object has no attribute 'find' — and because the call happens outside the guarded block, the exception propagates uncaught out of main_init, killing the entire init-local stage.

On a NoCloud/local-datasource boot (e.g. Raspberry Pi OS via Raspberry Pi Imager), this cascades to fail cloud-init-local.service, cloud-init-network.service, cloud-config.service, and cloud-final.service on every subsequent boot — write_files, runcmd, and (critically) network-config rendering never run again until the underlying config is fixed. On a headless device this silently and permanently breaks network provisioning, with no user-facing error beyond the log file.

Steps to reproduce the problem

  1. Set a purely-numeric string as the hostname in user-data:

    #cloud-config
    hostname: "123456"
    
  2. Boot with this cloud-config via the NoCloud datasource (dsmode: local).

  3. Inspect /var/log/cloud-init.loginit-local fails with the traceback below, and cloud-init status --long reports failure for all stages.

Reproduced specifically with Raspberry Pi Imager's cloud-init-based headless setup (user-data + meta-data + network-config seeded via file:///boot/firmware), but the crash is in generic cloudinit/util.py and cloudinit/cmd/main.py code, not anything Raspberry Pi OS-specific — it should reproduce identically on any NoCloud (or other datasource) boot where a numeric hostname reaches get_hostname_fqdn().

Environment details

  • Cloud-init version: 25.2
  • Operating System Distribution: Raspberry Pi OS (Debian 13 "Bookworm" based), aarch64
  • Cloud provider, platform or installer type: Raspberry Pi Imager (NoCloud datasource, dsmode: local, seeded from file:///boot/firmware)

cloud-init logs

2026-08-14 18:26:13,103 - main.py[ERROR]: failed stage init-local
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/cloudinit/cmd/main.py", line 963, in status_wrapper
    ret = functor(name, args)
  File "/usr/lib/python3/dist-packages/cloudinit/cmd/main.py", line 591, in main_init
    _maybe_set_hostname(init, stage="local", retry_stage="network")
  File "/usr/lib/python3/dist-packages/cloudinit/cmd/main.py", line 1046, in _maybe_set_hostname
    (hostname, _fqdn, _) = util.get_hostname_fqdn(init.cfg, cloud, metadata_only=True)
  File "/usr/lib/python3/dist-packages/cloudinit/util.py", line 1224, in get_hostname_fqdn
    if "hostname" in cfg and cfg["hostname"].find(".") > 0:
AttributeError: 'int' object has no attribute 'find'
failed run of stage init-local
------------------------------------------------------------
systemd[1]: cloud-init-local.service: Main process exited, code=exited, status=1/FAILURE
systemd[1]: cloud-init-local.service: Failed with result 'exit-code'.
systemd[1]: Failed to start cloud-init-local.service - Cloud-init: Local Stage (pre-network).
systemd[1]: cloud-init-network.service: Main process exited, code=exited, status=1/FAILURE
systemd[1]: cloud-init-network.service: Failed with result 'exit-code'.
systemd[1]: Failed to start cloud-init-network.service - Cloud-init: Network Stage.
systemd[1]: Failed to start cloud-config.service - Cloud-init: Config Stage.
systemd[1]: Failed to start cloud-final.service - Cloud-init: Final Stage.

Same traceback recurs identically on every boot from the point a numeric hostname is first consumed onward (confirmed across 20+ boots spanning several days on the reporter's device); the very first boot instead hit the same underlying AttributeError, but through the module-pipeline call path (cc_set_hostname under modules.py), where it is caught and logged only as a WARNING rather than aborting the stage:

handlers.py[DEBUG]: finish: init-local/config-set_hostname: FAIL: running config-set_hostname with frequency once-per-instance
log_util.py[WARNING]: Running module set_hostname (<module 'cloudinit.config.cc_set_hostname' ...>) failed

Suggested fix: either str(cfg["hostname"]).find(".") (and equivalent casts elsewhere in get_hostname_fqdn) in cloudinit/util.py, or move the util.get_hostname_fqdn(...) call in _maybe_set_hostname inside the existing try/except block so it fails as gracefully as the cc_set_hostname.handle(...) call right below it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working correctlynewAn issue that still needs triage

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions