diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml
index 2717cf0..ffa973a 100644
--- a/.github/workflows/test.yaml
+++ b/.github/workflows/test.yaml
@@ -24,8 +24,8 @@
       matrix:
         sdk: [dev]
     steps:
-      - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
-      - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+      - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3
+      - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
         with:
           sdk: ${{ matrix.sdk }}
       - id: install
@@ -52,8 +52,8 @@
         sdk: [dev]
         shard: [0, 1, 2, 3, 4, 5, 6]
     steps:
-      - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c
-      - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46
+      - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3
+      - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f
         with:
           sdk: ${{ matrix.sdk }}
       - name: Install dependencies
diff --git a/lib/src/command/cache_add.dart b/lib/src/command/cache_add.dart
index 763856e..85c2c5d 100644
--- a/lib/src/command/cache_add.dart
+++ b/lib/src/command/cache_add.dart
@@ -72,15 +72,10 @@
     }
 
     Future<void> downloadVersion(id) async {
-      if (cache.contains(id)) {
-        // TODO(rnystrom): Include source and description if not hosted.
-        // See solve_report.dart for code to harvest.
+      final result = await cache.downloadPackage(id);
+      if (!result.didUpdate) {
         log.message('Already cached ${id.name} ${id.version}.');
-        return;
       }
-
-      // Download it.
-      await cache.downloadPackage(id);
     }
 
     if (argResults['all']) {
diff --git a/lib/src/command/dependency_services.dart b/lib/src/command/dependency_services.dart
index c56f413..0ddf6ef 100644
--- a/lib/src/command/dependency_services.dart
+++ b/lib/src/command/dependency_services.dart
@@ -535,7 +535,7 @@
                     // This happens when we resolved a package from a legacy
                     // server not providing archive_sha256. As a side-effect of
                     // downloading the package we compute and store the sha256.
-                    package = await cache.downloadPackage(package);
+                    package = (await cache.downloadPackage(package)).packageId;
                   }
                 }
               } else {
diff --git a/lib/src/entrypoint.dart b/lib/src/entrypoint.dart
index c4cf03e..4d19989 100644
--- a/lib/src/entrypoint.dart
+++ b/lib/src/entrypoint.dart
@@ -988,14 +988,7 @@
 The lower bound of "sdk: '$dartSdkConstraint'" must be 2.12.0'
 or higher to enable null safety.
 
-The current version of the Dart SDK (${sdk.version}) does not support non-null
-safety code.
-
-Consider using an older, compatible Dart SDK or try the following sdk
-constraint:
-
-environment:
-  sdk: '${suggestedConstraint.asCompatibleWithIfPossible()}'
+The current Dart SDK (${sdk.version}) only supports null safety.
 
 For details, see https://dart.dev/null-safety
 ''');
diff --git a/lib/src/solver/result.dart b/lib/src/solver/result.dart
index bb70ef1..ce841fb 100644
--- a/lib/src/solver/result.dart
+++ b/lib/src/solver/result.dart
@@ -67,9 +67,10 @@
         if (id.source is CachedSource) {
           return await withDependencyType(_root.pubspec.dependencyType(id.name),
               () async {
-            return await cache.downloadPackage(
+            return (await cache.downloadPackage(
               id,
-            );
+            ))
+                .packageId;
           });
         }
         return id;
diff --git a/lib/src/source/cached.dart b/lib/src/source/cached.dart
index 9818146..933b08c 100644
--- a/lib/src/source/cached.dart
+++ b/lib/src/source/cached.dart
@@ -52,11 +52,6 @@
   /// the system cache.
   Future<Pubspec> describeUncached(PackageId id, SystemCache cache);
 
-  /// Determines if the package identified by [id] is already downloaded to the
-  /// system cache.
-  bool isInSystemCache(PackageId id, SystemCache cache) =>
-      dirExists(getDirectoryInCache(id, cache));
-
   /// Downloads the package identified by [id] to the system cache.
   Future<DownloadPackageResult> downloadToSystemCache(
     PackageId id,
diff --git a/lib/src/source/hosted.dart b/lib/src/source/hosted.dart
index 6f6632c..ae034d9 100644
--- a/lib/src/source/hosted.dart
+++ b/lib/src/source/hosted.dart
@@ -9,7 +9,7 @@
 import 'dart:typed_data';
 
 import 'package:collection/collection.dart'
-    show IterableExtension, IterableNullableExtension, ListEquality, maxBy;
+    show IterableExtension, IterableNullableExtension, maxBy;
 import 'package:crypto/crypto.dart';
 import 'package:http/http.dart' as http;
 import 'package:meta/meta.dart';
@@ -857,28 +857,6 @@
     );
   }
 
-  /// Determines if the package identified by [id] is already downloaded to the
-  /// system cache and has the expected content-hash.
-  @override
-  bool isInSystemCache(PackageId id, SystemCache cache) {
-    if ((id.description as ResolvedHostedDescription).sha256 != null) {
-      try {
-        final cachedSha256 = readTextFile(hashPath(id, cache));
-        if (!const ListEquality().equals(
-          hexDecode(cachedSha256),
-          (id.description as ResolvedHostedDescription).sha256,
-        )) {
-          return false;
-        }
-      } on io.IOException {
-        // Most likely the hash file was not written, because we had a legacy
-        // entry.
-        return false;
-      }
-    }
-    return dirExists(getDirectoryInCache(id, cache));
-  }
-
   /// The system cache directory for the hosted source contains subdirectories
   /// for each separate repository URL that's used on the system.
   ///
diff --git a/lib/src/system_cache.dart b/lib/src/system_cache.dart
index 90bd7d5..a83d395 100644
--- a/lib/src/system_cache.dart
+++ b/lib/src/system_cache.dart
@@ -126,16 +126,6 @@
     }
   }
 
-  /// Determines if the system cache contains the package identified by [id].
-  bool contains(PackageId id) {
-    final source = id.source;
-
-    if (source is CachedSource) {
-      return source.isInSystemCache(id, this);
-    }
-    throw ArgumentError('Package $id is not cacheable.');
-  }
-
   /// Create a new temporary directory within the system cache.
   ///
   /// The system cache maintains its own temporary directory that it uses to
@@ -241,7 +231,7 @@
   ///
   /// Returns [id] with an updated [ResolvedDescription], this can be different
   /// if the content-hash changed while downloading.
-  Future<PackageId> downloadPackage(PackageId id) async {
+  Future<DownloadPackageResult> downloadPackage(PackageId id) async {
     final source = id.source;
     assert(source is CachedSource);
     final result = await (source as CachedSource).downloadToSystemCache(
@@ -258,7 +248,7 @@
     if (result.didUpdate) {
       _ensureReadme();
     }
-    return result.packageId;
+    return result;
   }
 
   /// Get the latest version of [package].
diff --git a/lib/src/validator/analyze.dart b/lib/src/validator/analyze.dart
index d22da8d..c29fa9e 100644
--- a/lib/src/validator/analyze.dart
+++ b/lib/src/validator/analyze.dart
@@ -22,12 +22,7 @@
         .where(dirExists);
     final result = await runProcess(
       Platform.resolvedExecutable,
-      [
-        'analyze',
-        '--fatal-infos',
-        ...dirsToAnalyze,
-        p.join(entrypoint.rootDir, 'pubspec.yaml')
-      ],
+      ['analyze', ...dirsToAnalyze, p.join(entrypoint.rootDir, 'pubspec.yaml')],
     );
     if (result.exitCode != 0) {
       final limitedOutput = limitLength(result.stdout.join('\n'), 1000);
diff --git a/test/dart3_sdk_constraint_hack_test.dart b/test/dart3_sdk_constraint_hack_test.dart
index 5771ff6..354fb9a 100644
--- a/test/dart3_sdk_constraint_hack_test.dart
+++ b/test/dart3_sdk_constraint_hack_test.dart
@@ -19,7 +19,7 @@
 
     await pubGet(
       error: contains(
-        'The current version of the Dart SDK (3.5.0) does not support non-null\nsafety code.',
+        'The current Dart SDK (3.5.0) only supports null safety.',
       ),
       environment: {'_PUB_TEST_SDK_VERSION': '3.5.0'},
       exitCode: DATA,
@@ -51,7 +51,7 @@
 
     await pubGet(
       error: contains(
-        'The current version of the Dart SDK (3.5.0) does not support non-null\nsafety code.',
+        'The current Dart SDK (3.5.0) only supports null safety.',
       ),
       environment: {'_PUB_TEST_SDK_VERSION': '3.5.0'},
       exitCode: DATA,
@@ -68,7 +68,7 @@
 
     await pubGet(
       error: contains(
-        'The current version of the Dart SDK (3.5.0) does not support non-null\nsafety code.',
+        'The current Dart SDK (3.5.0) only supports null safety.',
       ),
       environment: {'_PUB_TEST_SDK_VERSION': '3.5.0'},
       exitCode: DATA,
diff --git a/test/get/sdk_constraint_required_test.dart b/test/get/sdk_constraint_required_test.dart
index 50c6420..c897033 100644
--- a/test/get/sdk_constraint_required_test.dart
+++ b/test/get/sdk_constraint_required_test.dart
@@ -50,14 +50,7 @@
 The lower bound of "sdk: '>=2.9.0 <4.0.0'" must be 2.12.0'
 or higher to enable null safety.
 
-The current version of the Dart SDK (3.1.2+3) does not support non-null
-safety code.
-
-Consider using an older, compatible Dart SDK or try the following sdk
-constraint:
-
-environment:
-  sdk: '^3.1.0'
+The current Dart SDK (3.1.2+3) only supports null safety.
 
 For details, see https://dart.dev/null-safety
 ''',
diff --git a/test/testdata/goldens/directory_option_test/commands taking a --directory~-C parameter work.txt b/test/testdata/goldens/directory_option_test/commands taking a --directory~-C parameter work.txt
index 2729283..a0df7ef 100644
--- a/test/testdata/goldens/directory_option_test/commands taking a --directory~-C parameter work.txt
+++ b/test/testdata/goldens/directory_option_test/commands taking a --directory~-C parameter work.txt
@@ -98,11 +98,8 @@
 ## Section 10
 $ pub run -C myapp 'bin/app.dart'
 Building package executable...
-[STDERR] Failed to build test_pkg:app:
-[STDERR] myapp/bin/app.dart:1:1: Error: The specified language version is too high. The highest supported language version is 3.0.
-[STDERR] main() => print('Hi');
-[STDERR] ^
-[EXIT CODE] 1
+Built test_pkg:app.
+Hi
 
 -------------------------------- END OF OUTPUT ---------------------------------
 
diff --git a/test/validator/analyze_test.dart b/test/validator/analyze_test.dart
index 5a1e8b4..55c9779 100644
--- a/test/validator/analyze_test.dart
+++ b/test/validator/analyze_test.dart
@@ -34,7 +34,7 @@
   });
 
   test(
-      'follows analysis_options.yaml and should warn if package contains errors in pubspec.yaml',
+      'follows analysis_options.yaml and should not warn if package contains only infos',
       () async {
     await d.dir(appPath, [
       d.libPubspec(
@@ -53,6 +53,32 @@
 ''')
     ]).create();
 
+    await expectValidation();
+  });
+
+  test(
+      'follows analysis_options.yaml and should warn if package contains warnings in pubspec.yaml',
+      () async {
+    await d.dir(appPath, [
+      d.libPubspec(
+        'test_pkg', '1.0.0',
+        sdk: '^3.0.0',
+        // Using http where https is recommended.
+        extras: {'repository': 'http://repo.org/'},
+      ),
+      d.file('LICENSE', 'Eh, do what you want.'),
+      d.file('README.md', "This package isn't real."),
+      d.file('CHANGELOG.md', '# 1.0.0\nFirst version\n'),
+      d.file('analysis_options.yaml', '''
+linter:
+  rules:
+    - secure_pubspec_urls
+analyzer:
+  errors:
+    secure_pubspec_urls: warning
+''')
+    ]).create();
+
     await expectValidation(
       error: allOf([
         contains(
diff --git a/test/validator/language_version_test.dart b/test/validator/language_version_test.dart
index 5a198ae..c1e5f75 100644
--- a/test/validator/language_version_test.dart
+++ b/test/validator/language_version_test.dart
@@ -2,6 +2,10 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'dart:io';
+
+import 'package:pub/src/language_version.dart';
+import 'package:pub_semver/pub_semver.dart';
 import 'package:test/test.dart';
 
 import '../descriptor.dart' as d;
@@ -57,9 +61,12 @@
 
   group('should warn if it', () {
     test('opts in to a newer version.', () async {
+      final nextVersion =
+          Version.parse(Platform.version.split(' ').first).nextMajor;
       await setup(
         sdkConstraint: '^3.0.0',
-        libraryLanguageVersion: '3.1',
+        libraryLanguageVersion:
+            LanguageVersion.fromVersion(nextVersion).toString(),
       );
       await expectValidationWarning(
         'The language version override can\'t specify a version greater than the latest known language version',