diff --git a/icu4c/source/common/localebuilder.cpp b/icu4c/source/common/localebuilder.cpp
index ddb5ea3b0a73..e6871b2a8c09 100644
--- a/icu4c/source/common/localebuilder.cpp
+++ b/icu4c/source/common/localebuilder.cpp
@@ -203,6 +203,7 @@ _copyExtensions(const Locale& from, icu::StringEnumeration *keywords,
 void
 _clearUAttributesAndKeyType(Locale& locale, UErrorCode& errorCode)
 {
+    if (U_FAILURE(errorCode)) { return; }
     // Clear Unicode attributes
     locale.setKeywordValue(kAttributeKey, "", errorCode);
 
@@ -218,6 +219,7 @@ _clearUAttributesAndKeyType(Locale& locale, UErrorCode& errorCode)
 void
 _setUnicodeExtensions(Locale& locale, const CharString& value, UErrorCode& errorCode)
 {
+    if (U_FAILURE(errorCode)) { return; }
     // Add the unicode extensions to extensions_
     CharString locale_str("und-u-", errorCode);
     locale_str.append(value, errorCode);
diff --git a/icu4c/source/common/localematcher.cpp b/icu4c/source/common/localematcher.cpp
index aa5ba0778c5c..6eaa31ac0327 100644
--- a/icu4c/source/common/localematcher.cpp
+++ b/icu4c/source/common/localematcher.cpp
@@ -4,6 +4,8 @@
 // localematcher.cpp
 // created: 2019may08 Markus W. Scherer
 
+#include <optional>
+
 #include "unicode/utypes.h"
 #include "unicode/localebuilder.h"
 #include "unicode/localematcher.h"
@@ -605,10 +607,11 @@ class LocaleLsrIterator {
 
 const Locale *LocaleMatcher::getBestMatch(const Locale &desiredLocale, UErrorCode &errorCode) const {
     if (U_FAILURE(errorCode)) { return nullptr; }
-    int32_t suppIndex = getBestSuppIndex(
+    std::optional<int32_t> suppIndex = getBestSuppIndex(
         getMaximalLsrOrUnd(likelySubtags, desiredLocale, errorCode),
         nullptr, errorCode);
-    return U_SUCCESS(errorCode) && suppIndex >= 0 ? supportedLocales[suppIndex] : defaultLocale;
+    return U_SUCCESS(errorCode) && suppIndex.has_value() ? supportedLocales[suppIndex.value()]
+                                                         : defaultLocale;
 }
 
 const Locale *LocaleMatcher::getBestMatch(Locale::Iterator &desiredLocales,
@@ -618,12 +621,14 @@ const Locale *LocaleMatcher::getBestMatch(Locale::Iterator &desiredLocales,
         return defaultLocale;
     }
     LocaleLsrIterator lsrIter(likelySubtags, desiredLocales, ULOCMATCH_TEMPORARY_LOCALES);
-    int32_t suppIndex = getBestSuppIndex(lsrIter.next(errorCode), &lsrIter, errorCode);
-    return U_SUCCESS(errorCode) && suppIndex >= 0 ? supportedLocales[suppIndex] : defaultLocale;
+    std::optional<int32_t> suppIndex = getBestSuppIndex(lsrIter.next(errorCode), &lsrIter, errorCode);
+    return U_SUCCESS(errorCode) && suppIndex.has_value() ? supportedLocales[suppIndex.value()]
+                                                         : defaultLocale;
 }
 
 const Locale *LocaleMatcher::getBestMatchForListString(
         StringPiece desiredLocaleList, UErrorCode &errorCode) const {
+    if (U_FAILURE(errorCode)) { return nullptr; }
     LocalePriorityList list(desiredLocaleList, errorCode);
     LocalePriorityList::Iterator iter = list.iterator();
     return getBestMatch(iter, errorCode);
@@ -634,13 +639,13 @@ LocaleMatcher::Result LocaleMatcher::getBestMatchResult(
     if (U_FAILURE(errorCode)) {
         return Result(nullptr, defaultLocale, -1, -1, false);
     }
-    int32_t suppIndex = getBestSuppIndex(
+    std::optional<int32_t> suppIndex = getBestSuppIndex(
         getMaximalLsrOrUnd(likelySubtags, desiredLocale, errorCode),
         nullptr, errorCode);
-    if (U_FAILURE(errorCode) || suppIndex < 0) {
+    if (U_FAILURE(errorCode) || !suppIndex.has_value()) {
         return Result(nullptr, defaultLocale, -1, -1, false);
     } else {
-        return Result(&desiredLocale, supportedLocales[suppIndex], 0, suppIndex, false);
+        return Result(&desiredLocale, supportedLocales[suppIndex.value()], 0, suppIndex.value(), false);
     }
 }
 
@@ -650,18 +655,19 @@ LocaleMatcher::Result LocaleMatcher::getBestMatchResult(
         return Result(nullptr, defaultLocale, -1, -1, false);
     }
     LocaleLsrIterator lsrIter(likelySubtags, desiredLocales, ULOCMATCH_TEMPORARY_LOCALES);
-    int32_t suppIndex = getBestSuppIndex(lsrIter.next(errorCode), &lsrIter, errorCode);
-    if (U_FAILURE(errorCode) || suppIndex < 0) {
+    std::optional<int32_t> suppIndex = getBestSuppIndex(lsrIter.next(errorCode), &lsrIter, errorCode);
+    if (U_FAILURE(errorCode) || !suppIndex.has_value()) {
         return Result(nullptr, defaultLocale, -1, -1, false);
     } else {
-        return Result(lsrIter.orphanRemembered(), supportedLocales[suppIndex],
-                      lsrIter.getBestDesiredIndex(), suppIndex, true);
+        return Result(lsrIter.orphanRemembered(), supportedLocales[suppIndex.value()],
+                      lsrIter.getBestDesiredIndex(), suppIndex.value(), true);
     }
 }
 
-int32_t LocaleMatcher::getBestSuppIndex(LSR desiredLSR, LocaleLsrIterator *remainingIter,
-                                        UErrorCode &errorCode) const {
-    if (U_FAILURE(errorCode)) { return -1; }
+std::optional<int32_t> LocaleMatcher::getBestSuppIndex(LSR desiredLSR,
+                                                       LocaleLsrIterator *remainingIter,
+                                                       UErrorCode &errorCode) const {
+    if (U_FAILURE(errorCode)) { return std::nullopt; }
     int32_t desiredIndex = 0;
     int32_t bestSupportedLsrIndex = -1;
     for (int32_t bestShiftedDistance = LocaleDistance::shiftDistance(thresholdDistance);;) {
@@ -684,7 +690,7 @@ int32_t LocaleMatcher::getBestSuppIndex(LSR desiredLSR, LocaleLsrIterator *remai
             bestShiftedDistance = LocaleDistance::getShiftedDistance(bestIndexAndDistance);
             if (remainingIter != nullptr) {
                 remainingIter->rememberCurrent(desiredIndex, errorCode);
-                if (U_FAILURE(errorCode)) { return -1; }
+                if (U_FAILURE(errorCode)) { return std::nullopt; }
             }
             bestSupportedLsrIndex = LocaleDistance::getIndex(bestIndexAndDistance);
         }
@@ -695,20 +701,21 @@ int32_t LocaleMatcher::getBestSuppIndex(LSR desiredLSR, LocaleLsrIterator *remai
             break;
         }
         desiredLSR = remainingIter->next(errorCode);
-        if (U_FAILURE(errorCode)) { return -1; }
+        if (U_FAILURE(errorCode)) { return std::nullopt; }
         ++desiredIndex;
     }
     if (bestSupportedLsrIndex < 0) {
         // no good match
-        return -1;
+        return std::nullopt;
     }
     return supportedIndexes[bestSupportedLsrIndex];
 }
 
 UBool LocaleMatcher::isMatch(const Locale &desired, const Locale &supported,
                              UErrorCode &errorCode) const {
+    if (U_FAILURE(errorCode)) { return false; }
     LSR suppLSR = getMaximalLsrOrUnd(likelySubtags, supported, errorCode);
-    if (U_FAILURE(errorCode)) { return 0; }
+    if (U_FAILURE(errorCode)) { return false; }
     const LSR *pSuppLSR = &suppLSR;
     int32_t indexAndDistance = localeDistance.getBestIndexAndDistance(
             getMaximalLsrOrUnd(likelySubtags, desired, errorCode),
@@ -718,9 +725,10 @@ UBool LocaleMatcher::isMatch(const Locale &desired, const Locale &supported,
 }
 
 double LocaleMatcher::internalMatch(const Locale &desired, const Locale &supported, UErrorCode &errorCode) const {
+    if (U_FAILURE(errorCode)) { return 0.; }
     // Returns the inverse of the distance: That is, 1-distance(desired, supported).
     LSR suppLSR = getMaximalLsrOrUnd(likelySubtags, supported, errorCode);
-    if (U_FAILURE(errorCode)) { return 0; }
+    if (U_FAILURE(errorCode)) { return 0.; }
     const LSR *pSuppLSR = &suppLSR;
     int32_t indexAndDistance = localeDistance.getBestIndexAndDistance(
             getMaximalLsrOrUnd(likelySubtags, desired, errorCode),
diff --git a/icu4c/source/common/locavailable.cpp b/icu4c/source/common/locavailable.cpp
index af07bf5fbab7..4a2600e88c59 100644
--- a/icu4c/source/common/locavailable.cpp
+++ b/icu4c/source/common/locavailable.cpp
@@ -101,10 +101,9 @@ icu::UInitOnce ginstalledLocalesInitOnce {};
 class AvailableLocalesSink : public ResourceSink {
   public:
     void put(const char *key, ResourceValue &value, UBool /*noFallback*/, UErrorCode &status) override {
+        if (U_FAILURE(status)) { return; }
         ResourceTable resIndexTable = value.getTable(status);
-        if (U_FAILURE(status)) {
-            return;
-        }
+        if (U_FAILURE(status)) { return; }
         for (int32_t i = 0; resIndexTable.getKeyAndValue(i, key, value); ++i) {
             ULocAvailableType type;
             if (uprv_strcmp(key, "InstalledLocales") == 0) {
@@ -138,7 +137,8 @@ class AvailableLocalesStringEnumeration : public StringEnumeration {
     AvailableLocalesStringEnumeration(ULocAvailableType type) : fType(type) {
     }
 
-    const char* next(int32_t *resultLength, UErrorCode&) override {
+    const char* next(int32_t *resultLength, UErrorCode &status) override {
+        if (U_FAILURE(status)) { return nullptr; }
         ULocAvailableType actualType = fType;
         int32_t actualIndex = fIndex++;
 
@@ -170,11 +170,13 @@ class AvailableLocalesStringEnumeration : public StringEnumeration {
         return result;
     }
 
-    void reset(UErrorCode&) override {
+    void reset(UErrorCode &status) override {
+        if (U_FAILURE(status)) { return; }
         fIndex = 0;
     }
 
-    int32_t count(UErrorCode&) const override {
+    int32_t count(UErrorCode &status) const override {
+        if (U_FAILURE(status)) { return 0; }
         if (fType == ULOC_AVAILABLE_WITH_LEGACY_ALIASES) {
             return gAvailableLocaleCounts[ULOC_AVAILABLE_DEFAULT]
                 + gAvailableLocaleCounts[ULOC_AVAILABLE_ONLY_LEGACY_ALIASES];
diff --git a/icu4c/source/common/locdispnames.cpp b/icu4c/source/common/locdispnames.cpp
index f1f0b065342c..a8316174b7ce 100644
--- a/icu4c/source/common/locdispnames.cpp
+++ b/icu4c/source/common/locdispnames.cpp
@@ -306,6 +306,7 @@ _getStringOrCopyKey(const char *path, const char *locale,
                     const char *substitute,
                     char16_t *dest, int32_t destCapacity,
                     UErrorCode &errorCode) {
+    if (U_FAILURE(errorCode)) { return 0; }
     const char16_t *s = nullptr;
     int32_t length = 0;
 
@@ -368,14 +369,10 @@ _getDisplayNameForComponent(const char *locale,
                             UDisplayNameGetter *getter,
                             const char *tag,
                             UErrorCode &errorCode) {
+    if (U_FAILURE(errorCode)) { return 0; }
     UErrorCode localStatus;
     const char* root = nullptr;
 
-    /* argument checking */
-    if (U_FAILURE(errorCode)) {
-        return 0;
-    }
-
     if(destCapacity<0 || (destCapacity>0 && dest==nullptr)) {
         errorCode = U_ILLEGAL_ARGUMENT_ERROR;
         return 0;
@@ -422,6 +419,7 @@ uloc_getDisplayScript(const char* locale,
                       char16_t *dest, int32_t destCapacity,
                       UErrorCode *pErrorCode)
 {
+    if (U_FAILURE(*pErrorCode)) { return 0; }
     UErrorCode err = U_ZERO_ERROR;
     int32_t res = _getDisplayNameForComponent(locale, displayLocale, dest, destCapacity,
                 ulocimp_getScript, _kScriptsStandAlone, err);
diff --git a/icu4c/source/common/locid.cpp b/icu4c/source/common/locid.cpp
index f382041997c4..3a39e62f1c61 100644
--- a/icu4c/source/common/locid.cpp
+++ b/icu4c/source/common/locid.cpp
@@ -916,6 +916,8 @@ AliasData::loadData(UErrorCode &status)
  */
 AliasData*
 AliasDataBuilder::build(UErrorCode &status) {
+    if (U_FAILURE(status)) { return nullptr; }
+
     LocalUResourceBundlePointer metadata(
         ures_openDirect(nullptr, "metadata", &status));
     LocalUResourceBundlePointer metadataAlias(
@@ -1061,7 +1063,7 @@ AliasDataBuilder::build(UErrorCode &status) {
  */
 class AliasReplacer {
 public:
-    AliasReplacer(UErrorCode status) :
+    AliasReplacer(UErrorCode& status) :
             language(nullptr), script(nullptr), region(nullptr),
             extensions(nullptr),
             // store value in variants only once
@@ -1126,12 +1128,12 @@ class AliasReplacer {
     }
 
     // Gather fields and generate locale ID into out.
-    CharString& outputToString(CharString& out, UErrorCode status);
+    CharString& outputToString(CharString& out, UErrorCode& status);
 
     // Generate the lookup key.
     CharString& generateKey(const char* language, const char* region,
                             const char* variant, CharString& out,
-                            UErrorCode status);
+                            UErrorCode& status);
 
     void parseLanguageReplacement(const char* replacement,
                                   const char*& replaceLanguage,
@@ -1168,8 +1170,9 @@ class AliasReplacer {
 CharString&
 AliasReplacer::generateKey(
         const char* language, const char* region, const char* variant,
-        CharString& out, UErrorCode status)
+        CharString& out, UErrorCode& status)
 {
+    if (U_FAILURE(status)) { return out; }
     out.append(language, status);
     if (notEmpty(region)) {
         out.append(SEP_CHAR, status)
@@ -1587,8 +1590,9 @@ AliasReplacer::replaceTransformedExtensions(
 
 CharString&
 AliasReplacer::outputToString(
-    CharString& out, UErrorCode status)
+    CharString& out, UErrorCode& status)
 {
+    if (U_FAILURE(status)) { return out; }
     out.append(language, status);
     if (notEmpty(script)) {
         out.append(SEP_CHAR, status)
@@ -1778,6 +1782,7 @@ AliasReplacer::replace(const Locale& locale, CharString& out, UErrorCode& status
 bool
 canonicalizeLocale(const Locale& locale, CharString& out, UErrorCode& status)
 {
+    if (U_FAILURE(status)) { return false; }
     AliasReplacer replacer(status);
     return replacer.replace(locale, out, status);
 }
@@ -1787,6 +1792,8 @@ canonicalizeLocale(const Locale& locale, CharString& out, UErrorCode& status)
 bool
 isKnownCanonicalizedLocale(const char* locale, UErrorCode& status)
 {
+    if (U_FAILURE(status)) { return false; }
+
     if (    uprv_strcmp(locale, "c") == 0 ||
             uprv_strcmp(locale, "en") == 0 ||
             uprv_strcmp(locale, "en_US") == 0) {
@@ -2453,7 +2460,8 @@ class KeywordEnumeration : public StringEnumeration {
                 (int32_t)(current - keywords.data()), status);
     }
 
-    virtual int32_t count(UErrorCode &/*status*/) const override {
+    virtual int32_t count(UErrorCode& status) const override {
+        if (U_FAILURE(status)) { return 0; }
         const char *kw = keywords.data();
         int32_t result = 0;
         while(*kw) {
@@ -2483,12 +2491,14 @@ class KeywordEnumeration : public StringEnumeration {
     }
 
     virtual const UnicodeString* snext(UErrorCode& status) override {
+        if (U_FAILURE(status)) { return nullptr; }
         int32_t resultLength = 0;
         const char *s = next(&resultLength, status);
         return setChars(s, resultLength, status);
     }
 
-    virtual void reset(UErrorCode& /*status*/) override {
+    virtual void reset(UErrorCode& status) override {
+        if (U_FAILURE(status)) { return; }
         current = keywords.data();
     }
 };
@@ -2521,7 +2531,8 @@ class UnicodeKeywordEnumeration : public KeywordEnumeration {
         if (resultLength != nullptr) *resultLength = 0;
         return nullptr;
     }
-    virtual int32_t count(UErrorCode &/*status*/) const override {
+    virtual int32_t count(UErrorCode& status) const override {
+        if (U_FAILURE(status)) { return 0; }
         const char *kw = keywords.data();
         int32_t result = 0;
         while(*kw) {
@@ -2625,6 +2636,10 @@ void
 Locale::getUnicodeKeywordValue(StringPiece keywordName,
                                ByteSink& sink,
                                UErrorCode& status) const {
+    if (U_FAILURE(status)) {
+        return;
+    }
+
     // TODO: Remove the need for a const char* to a NUL terminated buffer.
     const CharString keywordName_nul(keywordName, status);
     if (U_FAILURE(status)) {
@@ -2632,7 +2647,6 @@ Locale::getUnicodeKeywordValue(StringPiece keywordName,
     }
 
     const char* legacy_key = uloc_toLegacyKey(keywordName_nul.data());
-
     if (legacy_key == nullptr) {
         status = U_ILLEGAL_ARGUMENT_ERROR;
         return;
@@ -2705,6 +2719,7 @@ void
 Locale::setKeywordValue(StringPiece keywordName,
                         StringPiece keywordValue,
                         UErrorCode& status) {
+    if (U_FAILURE(status)) { return; }
     // TODO: Remove the need for a const char* to a NUL terminated buffer.
     const CharString keywordName_nul(keywordName, status);
     const CharString keywordValue_nul(keywordValue, status);
@@ -2715,16 +2730,18 @@ void
 Locale::setUnicodeKeywordValue(StringPiece keywordName,
                                StringPiece keywordValue,
                                UErrorCode& status) {
+    if (U_FAILURE(status)) {
+        return;
+    }
+
     // TODO: Remove the need for a const char* to a NUL terminated buffer.
     const CharString keywordName_nul(keywordName, status);
     const CharString keywordValue_nul(keywordValue, status);
-
     if (U_FAILURE(status)) {
         return;
     }
 
     const char* legacy_key = uloc_toLegacyKey(keywordName_nul.data());
-
     if (legacy_key == nullptr) {
         status = U_ILLEGAL_ARGUMENT_ERROR;
         return;
diff --git a/icu4c/source/common/loclikely.cpp b/icu4c/source/common/loclikely.cpp
index afbceaaa9950..9e0f058b34a5 100644
--- a/icu4c/source/common/loclikely.cpp
+++ b/icu4c/source/common/loclikely.cpp
@@ -130,17 +130,17 @@ bool CHECK_TRAILING_VARIANT_SIZE(const char* variant, int32_t variantLength) {
     return true;
 }
 
-bool
+void
 _uloc_addLikelySubtags(const char* localeID,
                        icu::ByteSink& sink,
                        UErrorCode& err) {
     if (U_FAILURE(err)) {
-        return false;
+        return;
     }
 
     if (localeID == nullptr) {
         err = U_ILLEGAL_ARGUMENT_ERROR;
-        return false;
+        return;
     }
 
     icu::CharString lang;
@@ -150,12 +150,12 @@ _uloc_addLikelySubtags(const char* localeID,
     const char* trailing = nullptr;
     ulocimp_getSubtags(localeID, &lang, &script, &region, &variant, &trailing, err);
     if (U_FAILURE(err)) {
-        return false;
+        return;
     }
 
     if (!CHECK_TRAILING_VARIANT_SIZE(variant.data(), variant.length())) {
         err = U_ILLEGAL_ARGUMENT_ERROR;
-        return false;
+        return;
     }
 
     if (lang.length() > 3) {
@@ -164,7 +164,7 @@ _uloc_addLikelySubtags(const char* localeID,
             lang.clear();
         } else {
             err = U_ILLEGAL_ARGUMENT_ERROR;
-            return false;
+            return;
         }
     }
 
@@ -172,18 +172,18 @@ _uloc_addLikelySubtags(const char* localeID,
 
     const icu::LikelySubtags* likelySubtags = icu::LikelySubtags::getSingleton(err);
     if (U_FAILURE(err)) {
-        return false;
+        return;
     }
     // We need to keep l on the stack because lsr may point into internal
     // memory of l.
     icu::Locale l = icu::Locale::createFromName(localeID);
     if (l.isBogus()) {
         err = U_ILLEGAL_ARGUMENT_ERROR;
-        return false;
+        return;
     }
     icu::LSR lsr = likelySubtags->makeMaximizedLsrFrom(l, true, err);
     if (U_FAILURE(err)) {
-        return false;
+        return;
     }
     const char* language = lsr.language;
     if (uprv_strcmp(language, "und") == 0) {
@@ -202,16 +202,8 @@ _uloc_addLikelySubtags(const char* localeID,
         trailingLength,
         sink,
         err);
-
-    return U_SUCCESS(err);
 }
 
-// Add likely subtags to the sink
-// return true if the value in the sink is produced by a match during the lookup
-// return false if the value in the sink is the same as input because there are
-// no match after the lookup.
-bool _ulocimp_addLikelySubtags(const char*, icu::ByteSink&, UErrorCode&);
-
 void
 _uloc_minimizeSubtags(const char* localeID,
                       icu::ByteSink& sink,
@@ -290,12 +282,12 @@ uloc_addLikelySubtags(const char* localeID,
             maximizedLocaleID, maximizedLocaleIDCapacity);
 
     ulocimp_addLikelySubtags(localeID, sink, *status);
-    int32_t reslen = sink.NumberOfBytesAppended();
-
     if (U_FAILURE(*status)) {
-        return sink.Overflowed() ? reslen : -1;
+        return 0;
     }
 
+    int32_t reslen = sink.NumberOfBytesAppended();
+
     if (sink.Overflowed()) {
         *status = U_BUFFER_OVERFLOW_ERROR;
     } else {
@@ -306,29 +298,17 @@ uloc_addLikelySubtags(const char* localeID,
     return reslen;
 }
 
-namespace {
-bool
-_ulocimp_addLikelySubtags(const char* localeID,
-                          icu::ByteSink& sink,
-                          UErrorCode& status) {
+U_EXPORT void
+ulocimp_addLikelySubtags(const char* localeID,
+                         icu::ByteSink& sink,
+                         UErrorCode& status) {
+    if (U_FAILURE(status)) { return; }
     icu::CharString localeBuffer;
     {
         icu::CharStringByteSink localeSink(&localeBuffer);
         ulocimp_canonicalize(localeID, localeSink, status);
     }
-    if (U_SUCCESS(status)) {
-        return _uloc_addLikelySubtags(localeBuffer.data(), sink, status);
-    } else {
-        return false;
-    }
-}
-}  // namespace
-
-U_EXPORT void
-ulocimp_addLikelySubtags(const char* localeID,
-                         icu::ByteSink& sink,
-                         UErrorCode& status) {
-    _ulocimp_addLikelySubtags(localeID, sink, status);
+    _uloc_addLikelySubtags(localeBuffer.data(), sink, status);
 }
 
 U_CAPI int32_t U_EXPORT2
@@ -344,12 +324,12 @@ uloc_minimizeSubtags(const char* localeID,
             minimizedLocaleID, minimizedLocaleIDCapacity);
 
     ulocimp_minimizeSubtags(localeID, sink, false, *status);
-    int32_t reslen = sink.NumberOfBytesAppended();
-
     if (U_FAILURE(*status)) {
-        return sink.Overflowed() ? reslen : -1;
+        return 0;
     }
 
+    int32_t reslen = sink.NumberOfBytesAppended();
+
     if (sink.Overflowed()) {
         *status = U_BUFFER_OVERFLOW_ERROR;
     } else {
@@ -365,6 +345,7 @@ ulocimp_minimizeSubtags(const char* localeID,
                         icu::ByteSink& sink,
                         bool favorScript,
                         UErrorCode& status) {
+    if (U_FAILURE(status)) { return; }
     icu::CharString localeBuffer;
     {
         icu::CharStringByteSink localeSink(&localeBuffer);
diff --git a/icu4c/source/common/loclikelysubtags.cpp b/icu4c/source/common/loclikelysubtags.cpp
index 28adec4a7a49..c182191057f4 100644
--- a/icu4c/source/common/loclikelysubtags.cpp
+++ b/icu4c/source/common/loclikelysubtags.cpp
@@ -70,6 +70,7 @@ struct LikelySubtagsData {
     }
 
     void load(UErrorCode &errorCode) {
+        if (U_FAILURE(errorCode)) { return; }
         langInfoBundle = ures_openDirect(nullptr, "langInfo", &errorCode);
         if (U_FAILURE(errorCode)) { return; }
         StackUResourceBundle stackTempBundle;
@@ -230,6 +231,7 @@ struct LikelySubtagsData {
 private:
     bool readStrings(const ResourceTable &table, const char *key, ResourceValue &value,
                      LocalMemory<int32_t> &indexes, int32_t &length, UErrorCode &errorCode) {
+        if (U_FAILURE(errorCode)) { return false; }
         if (table.findValue(key, value)) {
             ResourceArray stringArray = value.getArray(errorCode);
             if (U_FAILURE(errorCode)) { return false; }
@@ -296,7 +298,7 @@ struct LikelySubtagsData {
     }
 
     UnicodeString toRegion(const ResourceArray& m49Array, ResourceValue &value, int encoded, UErrorCode &errorCode) {
-        if (encoded == 0 || encoded == 1) {
+        if (U_FAILURE(errorCode) || encoded == 0 || encoded == 1) {
             return UNICODE_STRING_SIMPLE("");
         }
         encoded &= 0x00ffffff;
@@ -314,6 +316,7 @@ struct LikelySubtagsData {
 
     bool readLSREncodedStrings(const ResourceTable &table, const char* key, ResourceValue &value, const ResourceArray& m49Array,
                      LocalMemory<int32_t> &indexes, int32_t &length, UErrorCode &errorCode) {
+        if (U_FAILURE(errorCode)) { return false; }
         if (table.findValue(key, value)) {
             const int32_t* vectors = value.getIntVector(length, errorCode);
             if (U_FAILURE(errorCode)) { return false; }
@@ -380,6 +383,7 @@ constexpr const char16_t* MACROREGION_HARDCODE[] = {
 
 constexpr char16_t RANGE_MARKER = 0x7E; /* '~' */
 void processMacroregionRange(const UnicodeString& regionName, UVector* newMacroRegions, UErrorCode& status) {
+    if (U_FAILURE(status)) { return; }
     int32_t rangeMarkerLocation = regionName.indexOf(RANGE_MARKER);
     char16_t buf[6];
     regionName.extract(buf,6,status);
@@ -399,6 +403,7 @@ void processMacroregionRange(const UnicodeString& regionName, UVector* newMacroR
 
 #if U_DEBUG
 UVector* loadMacroregions(UErrorCode &status) {
+    if (U_FAILURE(status)) { return nullptr; }
     LocalPointer<UVector> newMacroRegions(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status), status);
 
     LocalUResourceBundlePointer supplementalData(ures_openDirect(nullptr,"supplementalData",&status));
@@ -423,6 +428,7 @@ UVector* loadMacroregions(UErrorCode &status) {
 #endif // U_DEBUG
 
 UVector* getStaticMacroregions(UErrorCode &status) {
+    if (U_FAILURE(status)) { return nullptr; }
     LocalPointer<UVector> newMacroRegions(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status), status);
 
     if (U_FAILURE(status)) {
@@ -515,9 +521,10 @@ LikelySubtags::~LikelySubtags() {
 LSR LikelySubtags::makeMaximizedLsrFrom(const Locale &locale,
                                          bool returnInputIfUnmatch,
                                          UErrorCode &errorCode) const {
+    if (U_FAILURE(errorCode)) { return {}; }
     if (locale.isBogus()) {
         errorCode = U_ILLEGAL_ARGUMENT_ERROR;
-        return LSR("", "", "", LSR::EXPLICIT_LSR);
+        return {};
     }
     const char *name = locale.getName();
     if (uprv_isAtSign(name[0]) && name[1] == 'x' && name[2] == '=') {  // name.startsWith("@x=")
@@ -553,6 +560,7 @@ LSR LikelySubtags::makeMaximizedLsr(const char *language, const char *script, co
                                      const char *variant,
                                      bool returnInputIfUnmatch,
                                      UErrorCode &errorCode) const {
+    if (U_FAILURE(errorCode)) { return {}; }
     // Handle pseudolocales like en-XA, ar-XB, fr-PSCRACK.
     // They should match only themselves,
     // not other locales with what looks like the same language and script subtags.
@@ -607,6 +615,7 @@ LSR LikelySubtags::makeMaximizedLsr(const char *language, const char *script, co
 LSR LikelySubtags::maximize(const char *language, const char *script, const char *region,
                              bool returnInputIfUnmatch,
                              UErrorCode &errorCode) const {
+    if (U_FAILURE(errorCode)) { return {}; }
     return maximize({language, (int32_t)uprv_strlen(language)},
                     {script, (int32_t)uprv_strlen(script)},
                     {region, (int32_t)uprv_strlen(region)},
@@ -615,10 +624,10 @@ LSR LikelySubtags::maximize(const char *language, const char *script, const char
 }
 
 bool LikelySubtags::isMacroregion(StringPiece& region, UErrorCode& errorCode) const {
+    if (U_FAILURE(errorCode)) { return false; }
     // In Java, we use Region class. In C++, since Region is under i18n,
     // we read the same data used by Region into gMacroregions avoid dependency
     // from common to i18n/region.cpp
-    if (U_FAILURE(errorCode)) { return false; }
     umtx_initOnce(gInitOnce, &LikelySubtags::initLikelySubtags, errorCode);
     if (U_FAILURE(errorCode)) { return false; }
     UnicodeString str(UnicodeString::fromUTF8(region));
@@ -628,9 +637,7 @@ bool LikelySubtags::isMacroregion(StringPiece& region, UErrorCode& errorCode) co
 LSR LikelySubtags::maximize(StringPiece language, StringPiece script, StringPiece region,
                              bool returnInputIfUnmatch,
                              UErrorCode &errorCode) const {
-    if (U_FAILURE(errorCode)) {
-        return LSR(language, script, region, LSR::EXPLICIT_LSR, errorCode);
-    }
+    if (U_FAILURE(errorCode)) { return {}; }
     if (language.compare("und") == 0) {
         language = "";
     }
@@ -920,10 +927,9 @@ LSR LikelySubtags::minimizeSubtags(StringPiece language, StringPiece script,
                                     StringPiece region,
                                     bool favorScript,
                                     UErrorCode &errorCode) const {
+    if (U_FAILURE(errorCode)) { return {}; }
     LSR max = maximize(language, script, region, true, errorCode);
-    if (U_FAILURE(errorCode)) {
-        return max;
-    }
+    if (U_FAILURE(errorCode)) { return {}; }
     // If no match, return it.
     if (uprv_strlen(max.language) == 0 &&
         uprv_strlen(max.script) == 0 &&
@@ -936,9 +942,7 @@ LSR LikelySubtags::minimizeSubtags(StringPiece language, StringPiece script,
     }
     // try language
     LSR test = maximize(max.language, "", "", true, errorCode);
-    if (U_FAILURE(errorCode)) {
-        return max;
-    }
+    if (U_FAILURE(errorCode)) { return {}; }
     if (test.isEquivalentTo(max)) {
         return LSR(max.language, "", "", LSR::DONT_CARE_FLAGS, errorCode);
     }
@@ -947,27 +951,21 @@ LSR LikelySubtags::minimizeSubtags(StringPiece language, StringPiece script,
         // favor Region
         // try language and region
         test = maximize(max.language, "", max.region, true, errorCode);
-        if (U_FAILURE(errorCode)) {
-            return max;
-        }
+        if (U_FAILURE(errorCode)) { return {}; }
         if (test.isEquivalentTo(max)) {
             return LSR(max.language, "", max.region, LSR::DONT_CARE_FLAGS, errorCode);
         }
     }
     // try language and script
     test = maximize(max.language, max.script, "", true, errorCode);
-    if (U_FAILURE(errorCode)) {
-        return max;
-    }
+    if (U_FAILURE(errorCode)) { return {}; }
     if (test.isEquivalentTo(max)) {
         return LSR(max.language, max.script, "", LSR::DONT_CARE_FLAGS, errorCode);
     }
     if (favorScript) {
         // try language and region
         test = maximize(max.language, "", max.region, true, errorCode);
-        if (U_FAILURE(errorCode)) {
-            return max;
-        }
+        if (U_FAILURE(errorCode)) { return {}; }
         if (test.isEquivalentTo(max)) {
             return LSR(max.language, "", max.region, LSR::DONT_CARE_FLAGS, errorCode);
         }
diff --git a/icu4c/source/common/locmap.cpp b/icu4c/source/common/locmap.cpp
index a59c7ab4e3ff..d21a11148fa8 100644
--- a/icu4c/source/common/locmap.cpp
+++ b/icu4c/source/common/locmap.cpp
@@ -977,6 +977,7 @@ idCmp(const char* id1, const char* id2)
 uint32_t
 getHostID(const ILcidPosixMap *this_0, const char* posixID, UErrorCode& status)
 {
+    if (U_FAILURE(status)) { return locmap_root->hostID; }
     int32_t bestIdx = 0;
     int32_t bestIdxDiff = 0;
     int32_t posixIDlen = (int32_t)uprv_strlen(posixID);
@@ -1004,7 +1005,7 @@ getHostID(const ILcidPosixMap *this_0, const char* posixID, UErrorCode& status)
 
     /*no match found */
     status = U_ILLEGAL_ARGUMENT_ERROR;
-    return this_0->regionMaps->hostID;
+    return locmap_root->hostID;
 }
 
 const char*
@@ -1151,7 +1152,7 @@ uprv_convertToPosix(uint32_t hostid, char *posixID, int32_t posixIDCapacity, UEr
 
     /* no match found */
     *status = U_ILLEGAL_ARGUMENT_ERROR;
-    return -1;
+    return 0;
 }
 
 /*
@@ -1257,6 +1258,14 @@ uprv_convertToLCIDPlatform(const char* localeID, UErrorCode* status)
 U_CAPI uint32_t
 uprv_convertToLCID(const char *langID, const char* posixID, UErrorCode* status)
 {
+    if (U_FAILURE(*status) ||
+            langID == nullptr ||
+            posixID == nullptr ||
+            uprv_strlen(langID) < 2 ||
+            uprv_strlen(posixID) < 2) {
+        return locmap_root->hostID;
+    }
+
     // This function does the table lookup when native platform name->lcid conversion isn't available,
     // or for locales that don't follow patterns the platform expects.
     uint32_t   low    = 0;
@@ -1270,11 +1279,6 @@ uprv_convertToLCID(const char *langID, const char* posixID, UErrorCode* status)
     UErrorCode myStatus;
     uint32_t   idx;
 
-    /* Check for incomplete id. */
-    if (!langID || !posixID || uprv_strlen(langID) < 2 || uprv_strlen(posixID) < 2) {
-        return 0;
-    }
-
     /*Binary search for the map entry for normal cases */
 
     while (high > low)  /*binary search*/{
@@ -1319,5 +1323,5 @@ uprv_convertToLCID(const char *langID, const char* posixID, UErrorCode* status)
 
     /* no match found */
     *status = U_ILLEGAL_ARGUMENT_ERROR;
-    return 0;   /* return international (root) */
+    return locmap_root->hostID;   /* return international (root) */
 }
diff --git a/icu4c/source/common/locresdata.cpp b/icu4c/source/common/locresdata.cpp
index 05cd24c6ff94..56b27fe5a5b1 100644
--- a/icu4c/source/common/locresdata.cpp
+++ b/icu4c/source/common/locresdata.cpp
@@ -50,6 +50,7 @@ uloc_getTableStringWithFallback(const char *path, const char *locale,
                               int32_t *pLength,
                               UErrorCode *pErrorCode)
 {
+    if (U_FAILURE(*pErrorCode)) { return nullptr; }
 /*    char localeBuffer[ULOC_FULLNAME_CAPACITY*4];*/
     const char16_t *item=nullptr;
     UErrorCode errorCode;
@@ -159,45 +160,47 @@ _uloc_getOrientationHelper(const char* localeId,
 {
     ULayoutType result = ULOC_LAYOUT_UNKNOWN;
 
-    if (!U_FAILURE(status)) {
-        icu::CharString localeBuffer;
-        {
-            icu::CharStringByteSink sink(&localeBuffer);
-            ulocimp_canonicalize(localeId, sink, status);
-        }
+    if (U_FAILURE(status)) { return result; }
 
-        if (!U_FAILURE(status)) {
-            int32_t length = 0;
-            const char16_t* const value =
-                uloc_getTableStringWithFallback(
-                    nullptr,
-                    localeBuffer.data(),
-                    "layout",
-                    nullptr,
-                    key,
-                    &length,
-                    &status);
-
-            if (!U_FAILURE(status) && length != 0) {
-                switch(value[0])
-                {
-                case 0x0062: /* 'b' */
-                    result = ULOC_LAYOUT_BTT;
-                    break;
-                case 0x006C: /* 'l' */
-                    result = ULOC_LAYOUT_LTR;
-                    break;
-                case 0x0072: /* 'r' */
-                    result = ULOC_LAYOUT_RTL;
-                    break;
-                case 0x0074: /* 't' */
-                    result = ULOC_LAYOUT_TTB;
-                    break;
-                default:
-                    status = U_INTERNAL_PROGRAM_ERROR;
-                    break;
-                }
-            }
+    icu::CharString localeBuffer;
+    {
+        icu::CharStringByteSink sink(&localeBuffer);
+        ulocimp_canonicalize(localeId, sink, status);
+    }
+
+    if (U_FAILURE(status)) { return result; }
+
+    int32_t length = 0;
+    const char16_t* const value =
+        uloc_getTableStringWithFallback(
+            nullptr,
+            localeBuffer.data(),
+            "layout",
+            nullptr,
+            key,
+            &length,
+            &status);
+
+    if (U_FAILURE(status)) { return result; }
+
+    if (length != 0) {
+        switch(value[0])
+        {
+        case 0x0062: /* 'b' */
+            result = ULOC_LAYOUT_BTT;
+            break;
+        case 0x006C: /* 'l' */
+            result = ULOC_LAYOUT_LTR;
+            break;
+        case 0x0072: /* 'r' */
+            result = ULOC_LAYOUT_RTL;
+            break;
+        case 0x0074: /* 't' */
+            result = ULOC_LAYOUT_TTB;
+            break;
+        default:
+            status = U_INTERNAL_PROGRAM_ERROR;
+            break;
         }
     }
 
diff --git a/icu4c/source/common/uloc.cpp b/icu4c/source/common/uloc.cpp
index f5f2219540e8..c17b590bfcf4 100644
--- a/icu4c/source/common/uloc.cpp
+++ b/icu4c/source/common/uloc.cpp
@@ -553,17 +553,19 @@ namespace {
  */
 CharString locale_canonKeywordName(const char* keywordName, UErrorCode& status)
 {
+  if (U_FAILURE(status)) { return {}; }
   CharString result;
 
   for (; *keywordName != 0; keywordName++) {
     if (!UPRV_ISALPHANUM(*keywordName)) {
       status = U_ILLEGAL_ARGUMENT_ERROR; /* malformed keyword name */
-      return result;
+      return {};
     }
     result.append(uprv_tolower(*keywordName), status);
   }
   if (result.isEmpty()) {
     status = U_ILLEGAL_ARGUMENT_ERROR; /* empty keyword name */
+    return {};
   }
 
   return result;
@@ -592,6 +594,8 @@ ulocimp_getKeywords(const char* localeID,
                     bool valuesToo,
                     UErrorCode& status)
 {
+    if (U_FAILURE(status)) { return; }
+
     KeywordStruct keywordList[ULOC_MAX_NO_KEYWORDS];
 
     int32_t maxKeywords = ULOC_MAX_NO_KEYWORDS;
@@ -718,13 +722,12 @@ uloc_getKeywordValue(const char* localeID,
 
     CheckedArrayByteSink sink(buffer, bufferCapacity);
     ulocimp_getKeywordValue(localeID, keywordName, sink, *status);
-
-    int32_t reslen = sink.NumberOfBytesAppended();
-
     if (U_FAILURE(*status)) {
-        return reslen;
+        return 0;
     }
 
+    int32_t reslen = sink.NumberOfBytesAppended();
+
     if (sink.Overflowed()) {
         *status = U_BUFFER_OVERFLOW_ERROR;
     } else {
@@ -740,102 +743,102 @@ ulocimp_getKeywordValue(const char* localeID,
                         icu::ByteSink& sink,
                         UErrorCode& status)
 {
+    if (U_FAILURE(status)) { return; }
+
+    if (localeID == nullptr || keywordName == nullptr || keywordName[0] == 0) {
+        status = U_ILLEGAL_ARGUMENT_ERROR;
+        return;
+    }
+
     const char* startSearchHere = nullptr;
     const char* nextSeparator = nullptr;
 
-    if (localeID != nullptr && U_SUCCESS(status)) {
-      CharString tempBuffer;
-      const char* tmpLocaleID;
+    CharString tempBuffer;
+    const char* tmpLocaleID;
 
-      if (keywordName == nullptr || keywordName[0] == 0) {
-        status = U_ILLEGAL_ARGUMENT_ERROR;
-        return;
-      }
+    CharString canonKeywordName = locale_canonKeywordName(keywordName, status);
+    if (U_FAILURE(status)) {
+      return;
+    }
+
+    if (_hasBCP47Extension(localeID)) {
+      CharStringByteSink sink(&tempBuffer);
+      ulocimp_forLanguageTag(localeID, -1, sink, nullptr, status);
+      tmpLocaleID = U_SUCCESS(status) && !tempBuffer.isEmpty() ? tempBuffer.data() : localeID;
+    } else {
+        tmpLocaleID=localeID;
+    }
 
-      CharString canonKeywordName = locale_canonKeywordName(keywordName, status);
-      if (U_FAILURE(status)) {
+    startSearchHere = locale_getKeywordsStart(tmpLocaleID);
+    if(startSearchHere == nullptr) {
+        /* no keywords, return at once */
         return;
-      }
+    }
 
-      if (_hasBCP47Extension(localeID)) {
-        CharStringByteSink sink(&tempBuffer);
-        ulocimp_forLanguageTag(localeID, -1, sink, nullptr, status);
-        tmpLocaleID = U_SUCCESS(status) && !tempBuffer.isEmpty() ? tempBuffer.data() : localeID;
-      } else {
-          tmpLocaleID=localeID;
-      }
-
-      startSearchHere = locale_getKeywordsStart(tmpLocaleID);
-      if(startSearchHere == nullptr) {
-          /* no keywords, return at once */
-          return;
-      }
-
-      /* find the first keyword */
-      while(startSearchHere) {
-          const char* keyValueTail;
-
-          startSearchHere++; /* skip @ or ; */
-          nextSeparator = uprv_strchr(startSearchHere, '=');
-          if(!nextSeparator) {
-              status = U_ILLEGAL_ARGUMENT_ERROR; /* key must have =value */
-              return;
-          }
-          /* strip leading & trailing spaces (TC decided to tolerate these) */
-          while(*startSearchHere == ' ') {
-              startSearchHere++;
+    /* find the first keyword */
+    while(startSearchHere) {
+        const char* keyValueTail;
+
+        startSearchHere++; /* skip @ or ; */
+        nextSeparator = uprv_strchr(startSearchHere, '=');
+        if(!nextSeparator) {
+            status = U_ILLEGAL_ARGUMENT_ERROR; /* key must have =value */
+            return;
+        }
+        /* strip leading & trailing spaces (TC decided to tolerate these) */
+        while(*startSearchHere == ' ') {
+            startSearchHere++;
+        }
+        keyValueTail = nextSeparator;
+        while (keyValueTail > startSearchHere && *(keyValueTail-1) == ' ') {
+            keyValueTail--;
+        }
+        /* now keyValueTail points to first char after the keyName */
+        /* copy & normalize keyName from locale */
+        if (startSearchHere == keyValueTail) {
+            status = U_ILLEGAL_ARGUMENT_ERROR; /* empty keyword name in passed-in locale */
+            return;
+        }
+        CharString localeKeywordName;
+        while (startSearchHere < keyValueTail) {
+          if (!UPRV_ISALPHANUM(*startSearchHere)) {
+            status = U_ILLEGAL_ARGUMENT_ERROR; /* malformed keyword name */
+            return;
           }
-          keyValueTail = nextSeparator;
-          while (keyValueTail > startSearchHere && *(keyValueTail-1) == ' ') {
+          localeKeywordName.append(uprv_tolower(*startSearchHere++), status);
+        }
+        if (U_FAILURE(status)) {
+            return;
+        }
+
+        startSearchHere = uprv_strchr(nextSeparator, ';');
+
+        if (canonKeywordName == localeKeywordName) {
+             /* current entry matches the keyword. */
+           nextSeparator++; /* skip '=' */
+            /* First strip leading & trailing spaces (TC decided to tolerate these) */
+            while(*nextSeparator == ' ') {
+              nextSeparator++;
+            }
+            keyValueTail = (startSearchHere)? startSearchHere: nextSeparator + uprv_strlen(nextSeparator);
+            while(keyValueTail > nextSeparator && *(keyValueTail-1) == ' ') {
               keyValueTail--;
-          }
-          /* now keyValueTail points to first char after the keyName */
-          /* copy & normalize keyName from locale */
-          if (startSearchHere == keyValueTail) {
-              status = U_ILLEGAL_ARGUMENT_ERROR; /* empty keyword name in passed-in locale */
-              return;
-          }
-          CharString localeKeywordName;
-          while (startSearchHere < keyValueTail) {
-            if (!UPRV_ISALPHANUM(*startSearchHere)) {
-              status = U_ILLEGAL_ARGUMENT_ERROR; /* malformed keyword name */
-              return;
             }
-            localeKeywordName.append(uprv_tolower(*startSearchHere++), status);
-          }
-          if (U_FAILURE(status)) {
+            /* Now copy the value, but check well-formedness */
+            if (nextSeparator == keyValueTail) {
+              status = U_ILLEGAL_ARGUMENT_ERROR; /* empty key value name in passed-in locale */
               return;
-          }
-
-          startSearchHere = uprv_strchr(nextSeparator, ';');
-
-          if (canonKeywordName == localeKeywordName) {
-               /* current entry matches the keyword. */
-             nextSeparator++; /* skip '=' */
-              /* First strip leading & trailing spaces (TC decided to tolerate these) */
-              while(*nextSeparator == ' ') {
-                nextSeparator++;
-              }
-              keyValueTail = (startSearchHere)? startSearchHere: nextSeparator + uprv_strlen(nextSeparator);
-              while(keyValueTail > nextSeparator && *(keyValueTail-1) == ' ') {
-                keyValueTail--;
-              }
-              /* Now copy the value, but check well-formedness */
-              if (nextSeparator == keyValueTail) {
-                status = U_ILLEGAL_ARGUMENT_ERROR; /* empty key value name in passed-in locale */
+            }
+            while (nextSeparator < keyValueTail) {
+              if (!UPRV_ISALPHANUM(*nextSeparator) && !UPRV_OK_VALUE_PUNCTUATION(*nextSeparator)) {
+                status = U_ILLEGAL_ARGUMENT_ERROR; /* malformed key value */
                 return;
               }
-              while (nextSeparator < keyValueTail) {
-                if (!UPRV_ISALPHANUM(*nextSeparator) && !UPRV_OK_VALUE_PUNCTUATION(*nextSeparator)) {
-                  status = U_ILLEGAL_ARGUMENT_ERROR; /* malformed key value */
-                  return;
-                }
-                /* Should we lowercase value to return here? Tests expect as-is. */
-                sink.Append(nextSeparator++, 1);
-              }
-              return;
-          }
-      }
+              /* Should we lowercase value to return here? Tests expect as-is. */
+              sink.Append(nextSeparator++, 1);
+            }
+            return;
+        }
     }
 }
 
@@ -845,9 +848,7 @@ uloc_setKeywordValue(const char* keywordName,
                      char* buffer, int32_t bufferCapacity,
                      UErrorCode* status)
 {
-    if (U_FAILURE(*status)) {
-        return -1;
-    }
+    if (U_FAILURE(*status)) { return 0; }
 
     if (bufferCapacity <= 1) {
         *status = U_ILLEGAL_ARGUMENT_ERROR;
@@ -870,8 +871,7 @@ uloc_setKeywordValue(const char* keywordName,
             keywords, keywordName, keywordValue, sink, *status);
 
     if (U_FAILURE(*status)) {
-        // A positive return value is a length, otherwise it's an error code.
-        return reslen > 0 ? reslen + baseLen : reslen;
+        return *status == U_BUFFER_OVERFLOW_ERROR ? reslen + baseLen : 0;
     }
 
     // See the documentation for this function, it's guaranteed to never
@@ -904,6 +904,8 @@ ulocimp_setKeywordValue(const char* keywords,
                         ByteSink& sink,
                         UErrorCode& status)
 {
+    if (U_FAILURE(status)) { return 0; }
+
     /* TODO: sorting. removal. */
     int32_t needLen = 0;
     int32_t rc;
@@ -914,9 +916,6 @@ ulocimp_setKeywordValue(const char* keywords,
     bool handledInputKeyAndValue = false;
     char keyValuePrefix = '@';
 
-    if (U_FAILURE(status)) {
-        return -1;
-    }
     if (status == U_STRING_NOT_TERMINATED_WARNING) {
         status = U_ZERO_ERROR;
     }
@@ -1132,7 +1131,7 @@ inline bool _isBCP47Extension(const char* p) {
  * The 'list' param should be LANGUAGES, LANGUAGES_3, COUNTRIES, or
  * COUNTRIES_3.
  */
-int16_t _findIndex(const char* const* list, const char* key)
+std::optional<int16_t> _findIndex(const char* const* list, const char* key)
 {
     const char* const* anchor = list;
     int32_t pass = 0;
@@ -1147,26 +1146,20 @@ int16_t _findIndex(const char* const* list, const char* key)
         }
         ++list;     /* skip final nullptr *CWB*/
     }
-    return -1;
+    return std::nullopt;
 }
 
 }  // namespace
 
 U_CFUNC const char*
 uloc_getCurrentCountryID(const char* oldID){
-    int32_t offset = _findIndex(DEPRECATED_COUNTRIES, oldID);
-    if (offset >= 0) {
-        return REPLACEMENT_COUNTRIES[offset];
-    }
-    return oldID;
+    std::optional<int16_t> offset = _findIndex(DEPRECATED_COUNTRIES, oldID);
+    return offset.has_value() ? REPLACEMENT_COUNTRIES[offset.value()] : oldID;
 }
 U_CFUNC const char*
 uloc_getCurrentLanguageID(const char* oldID){
-    int32_t offset = _findIndex(DEPRECATED_LANGUAGES, oldID);
-    if (offset >= 0) {
-        return REPLACEMENT_LANGUAGES[offset];
-    }
-    return oldID;
+    std::optional<int16_t> offset = _findIndex(DEPRECATED_LANGUAGES, oldID);
+    return offset.has_value() ? REPLACEMENT_LANGUAGES[offset.value()] : oldID;
 }
 
 namespace {
@@ -1230,9 +1223,9 @@ _getLanguage(const char* localeID,
         /* convert 3 character code to 2 character code if possible *CWB*/
         U_ASSERT(capacity >= 4);
         buffer[3] = '\0';
-        int32_t offset = _findIndex(LANGUAGES_3, buffer);
-        if(offset>=0) {
-            const char* const alias = LANGUAGES[offset];
+        std::optional<int16_t> offset = _findIndex(LANGUAGES_3, buffer);
+        if (offset.has_value()) {
+            const char* const alias = LANGUAGES[offset.value()];
             sink->Append(alias, (int32_t)uprv_strlen(alias));
             return;
         }
@@ -1311,9 +1304,9 @@ _getRegion(const char* localeID,
         /* convert 3 character code to 2 character code if possible *CWB*/
         U_ASSERT(capacity >= 4);
         buffer[3] = '\0';
-        int32_t offset = _findIndex(COUNTRIES_3, buffer);
-        if(offset>=0) {
-            const char* const alias = COUNTRIES[offset];
+        std::optional<int16_t> offset = _findIndex(COUNTRIES_3, buffer);
+        if (offset.has_value()) {
+            const char* const alias = COUNTRIES[offset.value()];
             sink->Append(alias, (int32_t)uprv_strlen(alias));
             return;
         }
@@ -1387,6 +1380,7 @@ _getVariant(const char* localeID,
 
 U_EXPORT CharString
 ulocimp_getLanguage(const char* localeID, UErrorCode& status) {
+    if (U_FAILURE(status)) { return {}; }
     CharString language;
     CharStringByteSink sink(&language);
     ulocimp_getSubtags(
@@ -1402,6 +1396,7 @@ ulocimp_getLanguage(const char* localeID, UErrorCode& status) {
 
 U_EXPORT CharString
 ulocimp_getScript(const char* localeID, UErrorCode& status) {
+    if (U_FAILURE(status)) { return {}; }
     CharString script;
     CharStringByteSink sink(&script);
     ulocimp_getSubtags(
@@ -1417,6 +1412,7 @@ ulocimp_getScript(const char* localeID, UErrorCode& status) {
 
 U_EXPORT CharString
 ulocimp_getRegion(const char* localeID, UErrorCode& status) {
+    if (U_FAILURE(status)) { return {}; }
     CharString region;
     CharStringByteSink sink(&region);
     ulocimp_getSubtags(
@@ -1432,6 +1428,7 @@ ulocimp_getRegion(const char* localeID, UErrorCode& status) {
 
 U_EXPORT CharString
 ulocimp_getVariant(const char* localeID, UErrorCode& status) {
+    if (U_FAILURE(status)) { return {}; }
     CharString variant;
     CharStringByteSink sink(&variant);
     ulocimp_getSubtags(
@@ -1454,6 +1451,8 @@ ulocimp_getSubtags(
         CharString* variant,
         const char** pEnd,
         UErrorCode& status) {
+    if (U_FAILURE(status)) { return; }
+
     std::optional<CharStringByteSink> languageSink;
     std::optional<CharStringByteSink> scriptSink;
     std::optional<CharStringByteSink> regionSink;
@@ -1619,12 +1618,11 @@ static const UEnumeration gKeywordsEnum = {
 U_CAPI UEnumeration* U_EXPORT2
 uloc_openKeywordList(const char *keywordList, int32_t keywordListSize, UErrorCode* status)
 {
+    if (U_FAILURE(*status)) { return nullptr; }
+
     LocalMemory<UKeywordsContext> myContext;
     LocalMemory<UEnumeration> result;
 
-    if (U_FAILURE(*status)) {
-        return nullptr;
-    }
     myContext.adoptInstead(static_cast<UKeywordsContext *>(uprv_malloc(sizeof(UKeywordsContext))));
     result.adoptInstead(static_cast<UEnumeration *>(uprv_malloc(sizeof(UEnumeration))));
     if (myContext.isNull() || result.isNull()) {
@@ -1648,13 +1646,13 @@ U_CAPI UEnumeration* U_EXPORT2
 uloc_openKeywords(const char* localeID,
                         UErrorCode* status)
 {
-    CharString tempBuffer;
-    const char* tmpLocaleID;
-
     if(status==nullptr || U_FAILURE(*status)) {
         return 0;
     }
 
+    CharString tempBuffer;
+    const char* tmpLocaleID;
+
     if (_hasBCP47Extension(localeID)) {
         CharStringByteSink sink(&tempBuffer);
         ulocimp_forLanguageTag(localeID, -1, sink, nullptr, *status);
@@ -1889,13 +1887,12 @@ uloc_getParent(const char*    localeID,
 
     CheckedArrayByteSink sink(parent, parentCapacity);
     ulocimp_getParent(localeID, sink, *err);
-
-    int32_t reslen = sink.NumberOfBytesAppended();
-
     if (U_FAILURE(*err)) {
-        return reslen;
+        return 0;
     }
 
+    int32_t reslen = sink.NumberOfBytesAppended();
+
     if (sink.Overflowed()) {
         *err = U_BUFFER_OVERFLOW_ERROR;
     } else {
@@ -1910,12 +1907,11 @@ ulocimp_getParent(const char* localeID,
                   icu::ByteSink& sink,
                   UErrorCode& err)
 {
+    if (U_FAILURE(err)) { return; }
+
     const char *lastUnderscore;
     int32_t i;
 
-    if (U_FAILURE(err))
-        return;
-
     if (localeID == nullptr)
         localeID = uloc_getDefault();
 
@@ -1956,13 +1952,12 @@ uloc_getLanguage(const char*    localeID,
             nullptr,
             nullptr,
             *err);
-
-    int32_t length = sink.NumberOfBytesAppended();
-
     if (U_FAILURE(*err)) {
-        return length;
+        return 0;
     }
 
+    int32_t length = sink.NumberOfBytesAppended();
+
     if (sink.Overflowed()) {
         *err = U_BUFFER_OVERFLOW_ERROR;
         return length;
@@ -1990,13 +1985,12 @@ uloc_getScript(const char*    localeID,
             nullptr,
             nullptr,
             *err);
-
-    int32_t length = sink.NumberOfBytesAppended();
-
     if (U_FAILURE(*err)) {
-        return length;
+        return 0;
     }
 
+    int32_t length = sink.NumberOfBytesAppended();
+
     if (sink.Overflowed()) {
         *err = U_BUFFER_OVERFLOW_ERROR;
         return length;
@@ -2024,13 +2018,12 @@ uloc_getCountry(const char* localeID,
             nullptr,
             nullptr,
             *err);
-
-    int32_t length = sink.NumberOfBytesAppended();
-
     if (U_FAILURE(*err)) {
-        return length;
+        return 0;
     }
 
+    int32_t length = sink.NumberOfBytesAppended();
+
     if (sink.Overflowed()) {
         *err = U_BUFFER_OVERFLOW_ERROR;
         return length;
@@ -2058,13 +2051,12 @@ uloc_getVariant(const char* localeID,
             &sink,
             nullptr,
             *err);
-
-    int32_t length = sink.NumberOfBytesAppended();
-
     if (U_FAILURE(*err)) {
-        return length;
+        return 0;
     }
 
+    int32_t length = sink.NumberOfBytesAppended();
+
     if (sink.Overflowed()) {
         *err = U_BUFFER_OVERFLOW_ERROR;
         return length;
@@ -2085,13 +2077,12 @@ uloc_getName(const char* localeID,
 
     CheckedArrayByteSink sink(name, nameCapacity);
     ulocimp_getName(localeID, sink, *err);
-
-    int32_t reslen = sink.NumberOfBytesAppended();
-
     if (U_FAILURE(*err)) {
-        return reslen;
+        return 0;
     }
 
+    int32_t reslen = sink.NumberOfBytesAppended();
+
     if (sink.Overflowed()) {
         *err = U_BUFFER_OVERFLOW_ERROR;
     } else {
@@ -2121,13 +2112,12 @@ uloc_getBaseName(const char* localeID,
 
     CheckedArrayByteSink sink(name, nameCapacity);
     ulocimp_getBaseName(localeID, sink, *err);
-
-    int32_t reslen = sink.NumberOfBytesAppended();
-
     if (U_FAILURE(*err)) {
-        return reslen;
+        return 0;
     }
 
+    int32_t reslen = sink.NumberOfBytesAppended();
+
     if (sink.Overflowed()) {
         *err = U_BUFFER_OVERFLOW_ERROR;
     } else {
@@ -2157,13 +2147,12 @@ uloc_canonicalize(const char* localeID,
 
     CheckedArrayByteSink sink(name, nameCapacity);
     ulocimp_canonicalize(localeID, sink, *err);
-
-    int32_t reslen = sink.NumberOfBytesAppended();
-
     if (U_FAILURE(*err)) {
-        return reslen;
+        return 0;
     }
 
+    int32_t reslen = sink.NumberOfBytesAppended();
+
     if (sink.Overflowed()) {
         *err = U_BUFFER_OVERFLOW_ERROR;
     } else {
@@ -2184,7 +2173,6 @@ ulocimp_canonicalize(const char* localeID,
 U_CAPI const char*  U_EXPORT2
 uloc_getISO3Language(const char* localeID)
 {
-    int16_t offset;
     UErrorCode err = U_ZERO_ERROR;
 
     if (localeID == nullptr)
@@ -2194,16 +2182,13 @@ uloc_getISO3Language(const char* localeID)
     CharString lang = ulocimp_getLanguage(localeID, err);
     if (U_FAILURE(err))
         return "";
-    offset = _findIndex(LANGUAGES, lang.data());
-    if (offset < 0)
-        return "";
-    return LANGUAGES_3[offset];
+    std::optional<int16_t> offset = _findIndex(LANGUAGES, lang.data());
+    return offset.has_value() ? LANGUAGES_3[offset.value()] : "";
 }
 
 U_CAPI const char*  U_EXPORT2
 uloc_getISO3Country(const char* localeID)
 {
-    int16_t offset;
     UErrorCode err = U_ZERO_ERROR;
 
     if (localeID == nullptr)
@@ -2213,11 +2198,8 @@ uloc_getISO3Country(const char* localeID)
     CharString cntry = ulocimp_getRegion(localeID, err);
     if (U_FAILURE(err))
         return "";
-    offset = _findIndex(COUNTRIES, cntry.data());
-    if (offset < 0)
-        return "";
-
-    return COUNTRIES_3[offset];
+    std::optional<int16_t> offset = _findIndex(COUNTRIES, cntry.data());
+    return offset.has_value() ? COUNTRIES_3[offset.value()] : "";
 }
 
 U_CAPI uint32_t  U_EXPORT2
diff --git a/icu4c/source/common/uloc_tag.cpp b/icu4c/source/common/uloc_tag.cpp
index b89867f771ac..878a34b6fd48 100644
--- a/icu4c/source/common/uloc_tag.cpp
+++ b/icu4c/source/common/uloc_tag.cpp
@@ -1169,12 +1169,9 @@ void _sortVariants(VariantListEntry* first) {
 
 void
 _appendVariantsToLanguageTag(const char* localeID, icu::ByteSink& sink, bool strict, bool& hadPosix, UErrorCode& status) {
-    UErrorCode tmpStatus = U_ZERO_ERROR;
-
-    if (U_FAILURE(status)) {
-        return;
-    }
+    if (U_FAILURE(status)) { return; }
 
+    UErrorCode tmpStatus = U_ZERO_ERROR;
     icu::CharString buf = ulocimp_getVariant(localeID, tmpStatus);
     if (U_FAILURE(tmpStatus) || tmpStatus == U_STRING_NOT_TERMINATED_WARNING) {
         if (strict) {
@@ -1280,6 +1277,8 @@ _appendVariantsToLanguageTag(const char* localeID, icu::ByteSink& sink, bool str
 
 void
 _appendKeywordsToLanguageTag(const char* localeID, icu::ByteSink& sink, bool strict, bool hadPosix, UErrorCode& status) {
+    if (U_FAILURE(status)) { return; }
+
     icu::MemoryPool<AttributeListEntry> attrPool;
     icu::MemoryPool<ExtensionListEntry> extPool;
     icu::MemoryPool<icu::CharString> strPool;
@@ -1522,6 +1521,8 @@ _appendKeywordsToLanguageTag(const char* localeID, icu::ByteSink& sink, bool str
  */
 void
 _appendLDMLExtensionAsKeywords(const char* ldmlext, ExtensionListEntry** appendTo, icu::MemoryPool<ExtensionListEntry>& extPool, icu::MemoryPool<icu::CharString>& kwdBuf, bool& posixVariant, UErrorCode& status) {
+    if (U_FAILURE(status)) { return; }
+
     const char *pTag;   /* beginning of current subtag */
     const char *pKwds;  /* beginning of key-type pairs */
     bool variantExists = posixVariant;
@@ -1782,6 +1783,8 @@ _appendLDMLExtensionAsKeywords(const char* ldmlext, ExtensionListEntry** appendT
 
 void
 _appendKeywords(ULanguageTag* langtag, icu::ByteSink& sink, UErrorCode& status) {
+    if (U_FAILURE(status)) { return; }
+
     int32_t i, n;
     int32_t len;
     ExtensionListEntry *kwdFirst = nullptr;
@@ -1791,10 +1794,6 @@ _appendKeywords(ULanguageTag* langtag, icu::ByteSink& sink, UErrorCode& status)
     icu::MemoryPool<icu::CharString> kwdBuf;
     bool posixVariant = false;
 
-    if (U_FAILURE(status)) {
-        return;
-    }
-
     n = ultag_getExtensionsSize(langtag);
 
     /* resolve locale keywords and reordering keys */
@@ -1877,14 +1876,10 @@ _appendKeywords(ULanguageTag* langtag, icu::ByteSink& sink, UErrorCode& status)
 }
 
 void
-_appendPrivateuseToLanguageTag(const char* localeID, icu::ByteSink& sink, bool strict, bool hadPosix, UErrorCode& status) {
-    (void)hadPosix;
-    UErrorCode tmpStatus = U_ZERO_ERROR;
-
-    if (U_FAILURE(status)) {
-        return;
-    }
+_appendPrivateuseToLanguageTag(const char* localeID, icu::ByteSink& sink, bool strict, bool /*hadPosix*/, UErrorCode& status) {
+    if (U_FAILURE(status)) { return; }
 
+    UErrorCode tmpStatus = U_ZERO_ERROR;
     icu::CharString buf = ulocimp_getVariant(localeID, tmpStatus);
     if (U_FAILURE(tmpStatus)) {
         if (strict) {
@@ -1986,6 +1981,8 @@ _appendPrivateuseToLanguageTag(const char* localeID, icu::ByteSink& sink, bool s
 
 ULanguageTag*
 ultag_parse(const char* tag, int32_t tagLen, int32_t* parsedLen, UErrorCode& status) {
+    if (U_FAILURE(status)) { return nullptr; }
+
     char *tagBuf;
     int16_t next;
     char *pSubtag, *pNext, *pLastGoodPosition;
@@ -2001,10 +1998,6 @@ ultag_parse(const char* tag, int32_t tagLen, int32_t* parsedLen, UErrorCode& sta
         *parsedLen = 0;
     }
 
-    if (U_FAILURE(status)) {
-        return nullptr;
-    }
-
     if (tagLen < 0) {
         tagLen = (int32_t)uprv_strlen(tag);
     }
@@ -2583,13 +2576,12 @@ uloc_toLanguageTag(const char* localeID,
 
     icu::CheckedArrayByteSink sink(langtag, langtagCapacity);
     ulocimp_toLanguageTag(localeID, sink, strict, *status);
-
-    int32_t reslen = sink.NumberOfBytesAppended();
-
     if (U_FAILURE(*status)) {
-        return reslen;
+        return 0;
     }
 
+    int32_t reslen = sink.NumberOfBytesAppended();
+
     if (sink.Overflowed()) {
         *status = U_BUFFER_OVERFLOW_ERROR;
     } else {
@@ -2605,6 +2597,8 @@ ulocimp_toLanguageTag(const char* localeID,
                       icu::ByteSink& sink,
                       bool strict,
                       UErrorCode& status) {
+    if (U_FAILURE(status)) { return; }
+
     icu::CharString canonical;
     UErrorCode tmpStatus = U_ZERO_ERROR;
     bool hadPosix = false;
@@ -2684,13 +2678,12 @@ uloc_forLanguageTag(const char* langtag,
 
     icu::CheckedArrayByteSink sink(localeID, localeIDCapacity);
     ulocimp_forLanguageTag(langtag, -1, sink, parsedLength, *status);
-
-    int32_t reslen = sink.NumberOfBytesAppended();
-
     if (U_FAILURE(*status)) {
-        return reslen;
+        return 0;
     }
 
+    int32_t reslen = sink.NumberOfBytesAppended();
+
     if (sink.Overflowed()) {
         *status = U_BUFFER_OVERFLOW_ERROR;
     } else {
@@ -2707,6 +2700,8 @@ ulocimp_forLanguageTag(const char* langtag,
                        icu::ByteSink& sink,
                        int32_t* parsedLength,
                        UErrorCode& status) {
+    if (U_FAILURE(status)) { return; }
+
     bool isEmpty = true;
     const char *subtag, *p;
     int32_t len;
diff --git a/icu4c/source/common/ulocale.cpp b/icu4c/source/common/ulocale.cpp
index 471ef0ce79a6..fada0afe3eb7 100644
--- a/icu4c/source/common/ulocale.cpp
+++ b/icu4c/source/common/ulocale.cpp
@@ -19,15 +19,17 @@ U_NAMESPACE_USE
 
 ULocale*
 ulocale_openForLocaleID(const char* localeID, int32_t length, UErrorCode* err) {
+    if (U_FAILURE(*err)) { return nullptr; }
     CharString str(length < 0 ? StringPiece(localeID) : StringPiece(localeID, length), *err);
-    if (U_FAILURE(*err)) return nullptr;
+    if (U_FAILURE(*err)) { return nullptr; }
     return EXTERNAL(icu::Locale::createFromName(str.data()).clone());
 }
 
 ULocale*
 ulocale_openForLanguageTag(const char* tag, int32_t length, UErrorCode* err) {
+  if (U_FAILURE(*err)) { return nullptr; }
   Locale l = icu::Locale::forLanguageTag(length < 0 ? StringPiece(tag) : StringPiece(tag, length), *err);
-  if (U_FAILURE(*err)) return nullptr;
+  if (U_FAILURE(*err)) { return nullptr; }
   return EXTERNAL(l.clone());
 }
 
@@ -57,10 +59,10 @@ int32_t ulocale_get ##N ( \
     CONST_INTERNAL(locale)->get ## N( \
         keywordLength < 0 ? StringPiece(keyword) : StringPiece(keyword, keywordLength), \
         sink, *err); \
-    int32_t reslen = sink.NumberOfBytesAppended(); \
     if (U_FAILURE(*err)) { \
-        return reslen; \
+        return 0; \
     } \
+    int32_t reslen = sink.NumberOfBytesAppended(); \
     if (sink.Overflowed()) { \
         *err = U_BUFFER_OVERFLOW_ERROR; \
     } else { \
diff --git a/icu4c/source/common/ulocbuilder.cpp b/icu4c/source/common/ulocbuilder.cpp
index a5af73bef490..a3e14fad6437 100644
--- a/icu4c/source/common/ulocbuilder.cpp
+++ b/icu4c/source/common/ulocbuilder.cpp
@@ -112,12 +112,13 @@ ULocale* ulocbld_buildULocale(ULocaleBuilder* builder, UErrorCode* err) {
 
 int32_t ulocbld_buildLocaleID(ULocaleBuilder* builder,
                               char* buffer, int32_t bufferCapacity, UErrorCode* err) {
+    if (U_FAILURE(*err)) { return 0; }
     if (builder == nullptr) {
         *err = U_ILLEGAL_ARGUMENT_ERROR;
         return 0;
     }
     icu::Locale l = INTERNAL(builder)->build(*err);
-    if (U_FAILURE(*err)) return 0;
+    if (U_FAILURE(*err)) { return 0; }
     int32_t length = (int32_t)(uprv_strlen(l.getName()));
     if (0 < length && length <= bufferCapacity) {
         uprv_memcpy(buffer, l.getName(), length);
@@ -127,18 +128,17 @@ int32_t ulocbld_buildLocaleID(ULocaleBuilder* builder,
 
 int32_t ulocbld_buildLanguageTag(ULocaleBuilder* builder,
                   char* buffer, int32_t bufferCapacity, UErrorCode* err) {
+    if (U_FAILURE(*err)) { return 0; }
     if (builder == nullptr) {
         *err = U_ILLEGAL_ARGUMENT_ERROR;
         return 0;
     }
     icu::Locale l = INTERNAL(builder)->build(*err);
-    if (U_FAILURE(*err)) return 0;
+    if (U_FAILURE(*err)) { return 0; }
     CheckedArrayByteSink sink(buffer, bufferCapacity);
     l.toLanguageTag(sink, *err);
+    if (U_FAILURE(*err)) { return 0; }
     int32_t reslen = sink.NumberOfBytesAppended();
-    if (U_FAILURE(*err)) {
-        return reslen;
-    }
     if (sink.Overflowed()) {
         *err = U_BUFFER_OVERFLOW_ERROR;
     } else {
diff --git a/icu4c/source/common/unicode/localematcher.h b/icu4c/source/common/unicode/localematcher.h
index 3e62c67c7e16..e16f1a31ca50 100644
--- a/icu4c/source/common/unicode/localematcher.h
+++ b/icu4c/source/common/unicode/localematcher.h
@@ -11,6 +11,8 @@
 
 #if U_SHOW_CPLUSPLUS_API
 
+#include <optional>
+
 #include "unicode/locid.h"
 #include "unicode/stringpiece.h"
 #include "unicode/uobject.h"
@@ -678,7 +680,7 @@ class U_COMMON_API LocaleMatcher : public UMemory {
 
     int32_t putIfAbsent(const LSR &lsr, int32_t i, int32_t suppLength, UErrorCode &errorCode);
 
-    int32_t getBestSuppIndex(LSR desiredLSR, LocaleLsrIterator *remainingIter, UErrorCode &errorCode) const;
+    std::optional<int32_t> getBestSuppIndex(LSR desiredLSR, LocaleLsrIterator *remainingIter, UErrorCode &errorCode) const;
 
     const LikelySubtags &likelySubtags;
     const LocaleDistance &localeDistance;
diff --git a/icu4c/source/common/unicode/locid.h b/icu4c/source/common/unicode/locid.h
index 9acc67341ab1..8ec8d3e3aece 100644
--- a/icu4c/source/common/unicode/locid.h
+++ b/icu4c/source/common/unicode/locid.h
@@ -1183,6 +1183,7 @@ Locale::operator!=(const    Locale&     other) const
 template<typename StringClass> inline StringClass
 Locale::toLanguageTag(UErrorCode& status) const
 {
+    if (U_FAILURE(status)) { return {}; }
     StringClass result;
     StringByteSink<StringClass> sink(&result);
     toLanguageTag(sink, status);
@@ -1222,6 +1223,7 @@ Locale::getName() const
 template<typename StringClass, typename OutputIterator> inline void
 Locale::getKeywords(OutputIterator iterator, UErrorCode& status) const
 {
+    if (U_FAILURE(status)) { return; }
     LocalPointer<StringEnumeration> keys(createKeywords(status));
     if (U_FAILURE(status) || keys.isNull()) {
         return;
@@ -1239,6 +1241,7 @@ Locale::getKeywords(OutputIterator iterator, UErrorCode& status) const
 template<typename StringClass, typename OutputIterator> inline void
 Locale::getUnicodeKeywords(OutputIterator iterator, UErrorCode& status) const
 {
+    if (U_FAILURE(status)) { return; }
     LocalPointer<StringEnumeration> keys(createUnicodeKeywords(status));
     if (U_FAILURE(status) || keys.isNull()) {
         return;
@@ -1256,6 +1259,7 @@ Locale::getUnicodeKeywords(OutputIterator iterator, UErrorCode& status) const
 template<typename StringClass> inline StringClass
 Locale::getKeywordValue(StringPiece keywordName, UErrorCode& status) const
 {
+    if (U_FAILURE(status)) { return {}; }
     StringClass result;
     StringByteSink<StringClass> sink(&result);
     getKeywordValue(keywordName, sink, status);
@@ -1265,6 +1269,7 @@ Locale::getKeywordValue(StringPiece keywordName, UErrorCode& status) const
 template<typename StringClass> inline StringClass
 Locale::getUnicodeKeywordValue(StringPiece keywordName, UErrorCode& status) const
 {
+    if (U_FAILURE(status)) { return {}; }
     StringClass result;
     StringByteSink<StringClass> sink(&result);
     getUnicodeKeywordValue(keywordName, sink, status);
diff --git a/icu4c/source/i18n/ulocdata.cpp b/icu4c/source/i18n/ulocdata.cpp
index a6854a527aa8..a1b2daa4436a 100644
--- a/icu4c/source/i18n/ulocdata.cpp
+++ b/icu4c/source/i18n/ulocdata.cpp
@@ -201,6 +201,8 @@ ulocdata_getDelimiter(ULocaleData *uld, ULocaleDataDelimiterType type,
 namespace {
 
 UResourceBundle * measurementTypeBundleForLocale(const char *localeID, const char *measurementType, UErrorCode *status){
+    if (U_FAILURE(*status)) { return nullptr; }
+
     UResourceBundle *rb;
     UResourceBundle *measTypeBundle = nullptr;
 
@@ -279,6 +281,7 @@ ulocdata_getPaperSize(const char* localeID, int32_t *height, int32_t *width, UEr
 
 U_CAPI void U_EXPORT2
 ulocdata_getCLDRVersion(UVersionInfo versionArray, UErrorCode *status) {
+    if (U_FAILURE(*status)) { return; }
     UResourceBundle *rb = nullptr;
     rb = ures_openDirect(nullptr, "supplementalData", status);
     ures_getVersionByKey(rb, "cldrVersion", versionArray, status);
diff --git a/icu4c/source/test/cintltst/cloctst.c b/icu4c/source/test/cintltst/cloctst.c
index 1f0a84b866c9..2935450be2ee 100644
--- a/icu4c/source/test/cintltst/cloctst.c
+++ b/icu4c/source/test/cintltst/cloctst.c
@@ -5946,19 +5946,19 @@ const errorData maximizeErrors[] = {
         "enfueiujhytdf",
         NULL,
         U_ILLEGAL_ARGUMENT_ERROR,
-        -1
+        0
     },
     {
         "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
         NULL,
         U_ILLEGAL_ARGUMENT_ERROR,
-        -1
+        0
     },
     {
         "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
         NULL,
         U_ILLEGAL_ARGUMENT_ERROR,
-        -1
+        0
     },
     {
         "en_Latn_US_POSIX@currency=EURO",
@@ -5979,13 +5979,13 @@ const errorData minimizeErrors[] = {
         "enfueiujhytdf",
         NULL,
         U_ILLEGAL_ARGUMENT_ERROR,
-        -1
+        0
     },
     {
         "en_THUJIOGIURJHGJFURYHFJGURYYYHHGJURHG",
         NULL,
         U_ILLEGAL_ARGUMENT_ERROR,
-        -1
+        0
     },
     {
         "en_Latn_US_POSIX@currency=EURO",
@@ -6010,7 +6010,7 @@ static int32_t getExpectedReturnValue(const errorData* data)
     }
     else
     {
-        return -1;
+        return 0;
     }
 }