diff --git a/src/utils/__tests__/PhutilUtilsTestCase.php b/src/utils/__tests__/PhutilUtilsTestCase.php
--- a/src/utils/__tests__/PhutilUtilsTestCase.php
+++ b/src/utils/__tests__/PhutilUtilsTestCase.php
@@ -1004,11 +1004,18 @@
 
     $uri = new PhutilURI('http://example.org/');
 
+    // Each test is defined in this way:
+    //   0: subject $value
+    //   1: expected result from phutil_nonempty_string($value)
+    //   2: expected result from phutil_nonempty_stringlike($value)
+    //   3: expected result from phutil_nonempty_scalar($value)
+    //   4: human test name
     $map = array(
       array(null, false, false, false, 'literal null'),
       array('', false, false, false, 'empty string'),
       array('x', true, true, true, 'nonempty string'),
-      array(false, null, null, null, 'bool'),
+      array(false, null, null, false, 'false bool'),
+      array(true, null, null, true, 'true bool'),
       array(1, null, null, true, 'integer'),
       array($uri, null, true, true, 'uri object'),
       array(2.5, null, null, true, 'float'),
diff --git a/src/utils/utils.php b/src/utils/utils.php
--- a/src/utils/utils.php
+++ b/src/utils/utils.php
@@ -2187,6 +2187,9 @@
  * string other than the empty string, integers, and floats are considered
  * scalar.
  *
+ * Note that booleans are also valid scalars, where false is considered empty,
+ * and true is non-empty since if you cast true to string, it's non-empty.
+ *
  * This method raises an exception if passed any other value.
  *
  * @param Value to test.
@@ -2205,6 +2208,14 @@
     return true;
   }
 
+  // Booleans are also valid scalars by PHP. Inventing the opposite can be
+  // too much esoteric and problematic.
+  //   false: empty,     because casted to string becomes ''  (empty)
+  //   true:  non-empty, because casted to string becomes '1' (non-empty)
+  if ($value === false || $value === true) {
+    return $value;
+  }
+
   if (is_object($value)) {
     try {
       $string = phutil_string_cast($value);