diff --git a/lib/src/command/global_activate.dart b/lib/src/command/global_activate.dart
index 53353ae..505ebe4 100644
--- a/lib/src/command/global_activate.dart
+++ b/lib/src/command/global_activate.dart
@@ -7,7 +7,7 @@
 import 'package:pub_semver/pub_semver.dart';
 
 import '../command.dart';
-import '../source/hosted.dart';
+import '../package_name.dart';
 import '../utils.dart';
 
 /// Handles the `global activate` pub command.
@@ -69,14 +69,6 @@
     }
 
     final overwrite = argResults['overwrite'] as bool;
-    Uri? hostedUrl;
-    if (argResults.wasParsed('hosted-url')) {
-      try {
-        hostedUrl = validateAndNormalizeHostedUrl(argResults['hosted-url']);
-      } on FormatException catch (e) {
-        usageException('Invalid hosted-url: $e');
-      }
-    }
 
     Iterable<String> args = argResults.rest;
 
@@ -115,6 +107,13 @@
       case 'hosted':
         var package = readArg('No package to activate given.');
 
+        PackageRef ref;
+        try {
+          ref = cache.hosted.refFor(package, url: argResults['hosted-url']);
+        } on FormatException catch (e) {
+          usageException('Invalid hosted-url: $e');
+        }
+
         // Parse the version constraint, if there is one.
         var constraint = VersionConstraint.any;
         if (args.isNotEmpty) {
@@ -127,11 +126,9 @@
 
         validateNoExtraArgs();
         return globals.activateHosted(
-          package,
-          constraint,
+          ref.withConstraint(constraint),
           executables,
           overwriteBinStubs: overwrite,
-          url: hostedUrl?.toString(),
         );
 
       case 'path':
diff --git a/lib/src/global_packages.dart b/lib/src/global_packages.dart
index 089016a..27c46ec 100644
--- a/lib/src/global_packages.dart
+++ b/lib/src/global_packages.dart
@@ -139,16 +139,16 @@
   /// [url] is an optional custom pub server URL. If not null, the package to be
   /// activated will be fetched from this URL instead of the default pub URL.
   Future<void> activateHosted(
-    String name,
-    VersionConstraint constraint,
+    PackageRange range,
     List<String>? executables, {
     required bool overwriteBinStubs,
     String? url,
   }) async {
     await _installInCache(
-        cache.hosted.refFor(name, url: url).withConstraint(constraint),
-        executables,
-        overwriteBinStubs: overwriteBinStubs);
+      range,
+      executables,
+      overwriteBinStubs: overwriteBinStubs,
+    );
   }
 
   /// Makes the local package at [path] globally active.
diff --git a/lib/src/pubspec.dart b/lib/src/pubspec.dart
index 8ac8023..f14133e 100644
--- a/lib/src/pubspec.dart
+++ b/lib/src/pubspec.dart
@@ -13,6 +13,7 @@
 import 'language_version.dart';
 import 'package_name.dart';
 import 'pubspec_parse.dart';
+import 'sdk.dart';
 import 'system_cache.dart';
 
 export 'pubspec_parse.dart' hide PubspecBase;
@@ -156,7 +157,10 @@
     // If a package is null safe it should also be compatible with dart 3.
     // Therefore we rewrite a null-safety enabled constraint with the upper
     // bound <3.0.0 to be have upper bound <4.0.0
-    if (constraint is VersionRange &&
+    //
+    // Only do this rewrite after dart 3.
+    if (sdk.version.major >= 3 &&
+        constraint is VersionRange &&
         LanguageVersion.fromSdkConstraint(constraint) >=
             LanguageVersion.firstVersionWithNullSafety &&
         // <3.0.0 is parsed into a max of 3.0.0-0, so that is what we look for
diff --git a/lib/src/source/hosted.dart b/lib/src/source/hosted.dart
index 2d481e4..6f590e1 100644
--- a/lib/src/source/hosted.dart
+++ b/lib/src/source/hosted.dart
@@ -51,7 +51,7 @@
 /// backwards compatibility with `pubspec.lock`-files which contain
 /// `https://pub.dartlang.org`.
 ///
-/// Throws [FormatException] if there is anything wrong [hostedUrl].
+/// Throws [FormatException] if there is anything wrong with [hostedUrl].
 ///
 /// [1]: ../../../doc/repository-spec-v2.md
 Uri validateAndNormalizeHostedUrl(String hostedUrl) {
@@ -194,8 +194,8 @@
   /// Returns a reference to a hosted package named [name].
   ///
   /// If [url] is passed, it's the URL of the pub server from which the package
-  /// should be downloaded. [url] most be normalized and validated using
-  /// [validateAndNormalizeHostedUrl].
+  /// should be downloaded. [url] will be normalized and validated using
+  /// [validateAndNormalizeHostedUrl]. This can throw a [FormatException].
   PackageRef refFor(String name, {String? url}) {
     final d = HostedDescription(name, url ?? defaultUrl);
     return PackageRef(name, d);
@@ -258,7 +258,7 @@
       name,
       version,
       ResolvedHostedDescription(
-        HostedDescription(name, Uri.parse(url).toString()),
+        HostedDescription(name, url),
         sha256: sha256 == null ? null : hexDecode(sha256),
       ),
     );
@@ -291,8 +291,7 @@
       // environment, we throw an error if something that looks like a URI is
       // used as a package name.
       if (canUseShorthandSyntax) {
-        return HostedDescription(
-            packageName, validateAndNormalizeHostedUrl(description).toString());
+        return HostedDescription(packageName, description);
       } else {
         if (_looksLikePackageName.hasMatch(description)) {
           // Valid use of `hosted: package` dependency with an old SDK
@@ -319,14 +318,11 @@
           'a minimum Dart SDK constraint of ${LanguageVersion.firstVersionWithShorterHostedSyntax}.0 or higher.');
     }
 
-    var url = defaultUrl;
     final u = description['url'];
-    if (u != null) {
-      if (u is! String) {
-        throw FormatException("The 'url' key must be a string value.");
-      }
-      url = validateAndNormalizeHostedUrl(u).toString();
+    if (u != null && u is! String) {
+      throw FormatException("The 'url' key must be a string value.");
     }
+    final url = u ?? defaultUrl;
 
     return HostedDescription(name, url);
   }
@@ -915,7 +911,7 @@
               package.name,
               package.version,
               ResolvedHostedDescription(
-                HostedDescription(package.name, url),
+                HostedDescription._(package.name, url),
                 sha256: null,
               ),
             );
@@ -1178,10 +1174,7 @@
         pubspec.name,
         pubspec.version,
         ResolvedHostedDescription(
-          HostedDescription(
-            pubspec.name,
-            validateAndNormalizeHostedUrl(cache.hosted.defaultUrl).toString(),
-          ),
+          HostedDescription(pubspec.name, defaultUrl),
           sha256: contentHash,
         ),
       );
@@ -1283,7 +1276,12 @@
   final String packageName;
   final String url;
 
-  HostedDescription(this.packageName, this.url);
+  HostedDescription._(this.packageName, this.url);
+  factory HostedDescription(String packageName, String url) =>
+      HostedDescription._(
+        packageName,
+        validateAndNormalizeHostedUrl(url).toString(),
+      );
 
   @override
   int get hashCode => Object.hash(packageName, url);
diff --git a/test/dart3_sdk_constraint_hack_test.dart b/test/dart3_sdk_constraint_hack_test.dart
index 7df3ee8..1a03ce5 100644
--- a/test/dart3_sdk_constraint_hack_test.dart
+++ b/test/dart3_sdk_constraint_hack_test.dart
@@ -108,4 +108,19 @@
       ),
     );
   });
+  test('Rewrite only happens after Dart 3', () async {
+    await d.dir(appPath, [
+      d.pubspec({
+        'name': 'myapp',
+        'environment': {'sdk': '>=2.19.1 <3.0.0'}
+      }),
+    ]).create();
+
+    await pubGet(
+      error: contains(
+        'Because myapp requires SDK version >=2.19.1 <3.0.0, version solving failed.',
+      ),
+      environment: {'_PUB_TEST_SDK_VERSION': '2.19.0'},
+    );
+  });
 }
diff --git a/test/lock_file_test.dart b/test/lock_file_test.dart
index 20e3976..7e01e7f 100644
--- a/test/lock_file_test.dart
+++ b/test/lock_file_test.dart
@@ -205,6 +205,41 @@
         }, throwsFormatException);
       });
 
+      test('Reads pub.dartlang.org as pub.dev in hosted descriptions', () {
+        final lockfile = LockFile.parse(
+          '''
+packages:
+  characters:
+    dependency: transitive
+    description:
+      name: characters
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "1.2.1"
+  retry:
+    dependency: transitive
+    description:
+      name: retry
+      url: "https://pub.dev"
+      sha256:
+    source: hosted
+    version: "1.0.0"
+''',
+          sources,
+        );
+        void expectComesFromPubDev(String name) {
+          final description = lockfile.packages[name]!.description.description
+              as HostedDescription;
+          expect(
+            description.url,
+            'https://pub.dev',
+          );
+        }
+
+        expectComesFromPubDev('characters');
+        expectComesFromPubDev('retry');
+      });
+
       test('ignores extra stuff in file', () {
         LockFile.parse('''
 extra: