duplicati/duplicati · error · UserInformationException

OpenStackMissingUsername

OpenStackMissingUsername

Error message

Missing required option: {0}

What it means

OpenStackStorage constructor throws UserInformationException('OpenStackMissingUsername') when AuthOptionsHelper.Parse(options, uri.Username, uri.Password) yields an auth object with !HasUsername. The username normally comes from the connection URI; its absence means the credentials were not supplied.

Source

Thrown at Duplicati/Library/Backend/OpenStack/OpenStackStorage.cs:129

        m_container = uri.Host ?? "";
        m_prefix = Util.AppendDirSeparator("/" + uri.Path, "/");
        _timeouts = TimeoutOptionsHelper.Parse(options);

        // For OpenStack we do not use a leading slash
        if (m_prefix.StartsWith("/", StringComparison.Ordinal))
            m_prefix = m_prefix.Substring(1);

        var auth = AuthOptionsHelper.Parse(options, uri.Username, uri.Password);

        options.TryGetValue(DOMAINNAME_OPTION, out m_domainName);
        options.TryGetValue(TENANTNAME_OPTION, out m_tenantName);
        options.TryGetValue(VERSION_OPTION, out m_version);
        options.TryGetValue(APIKEY_OPTION, out m_apikey);
        options.TryGetValue(REGION_OPTION, out m_region);

        if (!auth.HasUsername)
            throw new UserInformationException(Strings.OpenStack.MissingOptionError(AuthOptionsHelper.AuthUsernameOption), "OpenStackMissingUsername");

        m_username = auth.Username!;
        m_password = auth.Password;
        var authUri = options.GetValueOrDefault(AUTHURI_OPTION);
        if (string.IsNullOrWhiteSpace(authUri))
            throw new UserInformationException(Strings.OpenStack.MissingOptionError(AUTHURI_OPTION), "OpenStackMissingAuthUri");

        m_authUri = authUri;
        if (string.IsNullOrWhiteSpace(m_version) && m_authUri.EndsWith("/v3", StringComparison.OrdinalIgnoreCase))
            m_version = "v3";

        switch (m_version)
        {
            case "v3":
                if (string.IsNullOrWhiteSpace(m_password))
                    throw new UserInformationException(Strings.OpenStack.MissingOptionError(AuthOptionsHelper.AuthPasswordOption), "OpenStackMissingPassword");
                if (string.IsNullOrWhiteSpace(m_domainName))
                    throw new UserInformationException(Strings.OpenStack.MissingOptionError(DOMAINNAME_OPTION), "OpenStackMissingDomainName");

View on GitHub (pinned to 3f348be3e3)

Solutions

  1. Put the username in the backend URL: openstack://username@auth-endpoint/...
  2. Confirm the URI parsing path the backend uses (AuthOptionsHelper reads username from the URI authority).
  3. Re-create the backend via the GUI which splits username/host correctly.

Example fix

// before
openstack://auth.example.com/v3/container

// after
openstack://myuser@auth.example.com/v3/container
Defensive patterns

Strategy: validation

Validate before calling

if (string.IsNullOrWhiteSpace(uri.Username))
    throw new InvalidOperationException("OpenStack backend requires a username in the connection URI.");

Try / catch

try { storage = new OpenStackStorage(url, opts); }
catch (UserInformationException ex) when (ex.HelpID == "OpenStackMissingUsername")
{ ReportConfigError(ex.Message); throw; }

Prevention

When it happens

Trigger: Constructor at line 128-129: auth.HasUsername is false because uri.Username is empty and no equivalent option populates it.

Common situations: Backend URL written without the 'username@' segment; credentials moved into options but the OpenStack helper only reads username from the URI; secret/credential migration that dropped the username.

Related errors


AI-assisted analysis of duplicati/duplicati@3f348be3e3 (2026-08-13). Data as JSON: /api/errors/ddf21a78144be5bf. Report an issue: GitHub.