aws-sdk-android icon indicating copy to clipboard operation
aws-sdk-android copied to clipboard

Getting error wrapped.errorStream must not be null while uploading files on s3 bucket

Open girishacme opened this issue 2 years ago • 6 comments

Describe the bug Getting below exception while uploading assets:

    java.lang.NullPointerException: wrapped.errorStream must not be null
        at com.android.tools.appinspection.network.httpurl.TrackedHttpURLConnection.getErrorStream(TrackedHttpURLConnection.kt:155)
        at com.android.tools.appinspection.network.httpurl.HttpsURLConnectionWrapper.getErrorStream(HttpsURLConnectionWrapper.kt:130)
        at com.amazonaws.http.UrlHttpClient.createHttpResponse(UrlHttpClient.java:94)
        at com.amazonaws.http.UrlHttpClient.execute(UrlHttpClient.java:85)
        at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:386)
        at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:229)
        at com.amazonaws.services.cognitoidentity.AmazonCognitoIdentityClient.invoke(AmazonCognitoIdentityClient.java:1836)
        at com.amazonaws.services.cognitoidentity.AmazonCognitoIdentityClient.getCredentialsForIdentity(AmazonCognitoIdentityClient.java:750)
        at com.amazonaws.auth.CognitoCredentialsProvider.populateCredentialsWithCognito(CognitoCredentialsProvider.java:791)
        at com.amazonaws.auth.CognitoCredentialsProvider.startSession(CognitoCredentialsProvider.java:703)
        at com.amazonaws.auth.CognitoCredentialsProvider.refresh(CognitoCredentialsProvider.java:640)
        at com.amazonaws.auth.CognitoCachingCredentialsProvider.refresh(CognitoCachingCredentialsProvider.java:511)
        at com.amazonaws.auth.CognitoCachingCredentialsProvider.getIdentityId(CognitoCachingCredentialsProvider.java:453)
        at com.amazonaws.auth.CognitoCredentialsProvider.populateCredentialsWithCognito(CognitoCredentialsProvider.java:785)
        at com.amazonaws.auth.CognitoCredentialsProvider.startSession(CognitoCredentialsProvider.java:703)
        at com.amazonaws.auth.CognitoCredentialsProvider.refresh(CognitoCredentialsProvider.java:640)
        at com.amazonaws.auth.CognitoCachingCredentialsProvider.refresh(CognitoCachingCredentialsProvider.java:511)

To Reproduce A code sample or steps: public class Utils {

private ConcurrentHashMap<String, TransferUtility> transferUtilityConcurrentHashMap = new ConcurrentHashMap<>();
private final Context context;
private final GsonHelper gsonHelper;

Utils(Context context, GsonHelper gsonHelper) {
    this.context = context;
    this.gsonHelper = gsonHelper;
}
public TransferUtility getTransferUtility(SessionModel sessionModel) {
    TransferUtility sTransferUtility = transferUtilityConcurrentHashMap.get("12345");

    if (sTransferUtility != null) {
        return sTransferUtility;
    } else {
        return getNewTransferUtility(sessionModel);
    }
}

private TransferUtility getNewTransferUtility(SessionModel sessionModel) {
    AWSConfiguration awsConfiguration = getAWSConfiguration(sessionModel);
    TransferUtility sTransferUtility = TransferUtility.builder()
            .context(context)
            .s3Client(getS3Client(sessionModel.getRegionName(),
                    awsConfiguration))
            .awsConfiguration(awsConfiguration)
            .build();

    transferUtilityConcurrentHashMap.put("12345", sTransferUtility);
    return sTransferUtility;
}

private AmazonS3Client getS3Client(String regionString, AWSConfiguration awsConfiguration) {
    AmazonS3Client sS3Client = null;
    try {
        Region region = Region.getRegion(regionString);
        sS3Client = new AmazonS3Client(getCredProvider( awsConfiguration), region);
    } catch (Exception e) {
        Log.e("error: ", e);
    }
    return sS3Client;
}

private AWSCredentialsProvider getCredProvider(AWSConfiguration awsConfiguration) {
    AWSCredentialsProvider sMobileClient = null;

    final CountDownLatch latch = new CountDownLatch(1);
    AWSMobileClient.getInstance().initialize(context, awsConfiguration, new Callback<UserStateDetails>() {
        @Override
        public void onResult(UserStateDetails result) {
            latch.countDown();
        }

        @Override
        public void onError(Exception e) {
            Log.e("error: ", e);
            latch.countDown();
        }
    });
    try {
        latch.await();
        sMobileClient = AWSMobileClient.getInstance();
    } catch (InterruptedException e) {
        Log.e("error: ", e);
    }
    return sMobileClient;
}

private AWSConfiguration getAWSConfiguration(SessionModel sessionModel) {
    AWSConfig awsConfig = getAWSConfig(sessionModel);
    JSONObject jsonObject = null;
    String awsConfigString = gsonHelper.fromObjectToString(awsConfig);
    try {
        jsonObject = new JSONObject(awsConfigString);
    } catch (JSONException e) {
        Log.e("error" + e);
    }
    AWSConfiguration awsConfiguration = new AWSConfiguration(jsonObject);
    setLogin(sessionModel, awsConfiguration);
    return awsConfiguration;
}

private AWSConfig getAWSConfig(SessionModel sessionModel) {
    IdentityDefault identityDefault = new IdentityDefault();
    IdentityManager identityManager = new IdentityManager();
    identityManager.setIdentityDefault(identityDefault);

    CognitoDefault cognitoDefault = new CognitoDefault();
    cognitoDefault.setPoolId(sessionModel.getIdentityPoolId());
    cognitoDefault.setRegion(sessionModel.getRegionName());
    CognitoIdentity cognitoIdentity = new CognitoIdentity();
    cognitoIdentity.setCognitoDefault(cognitoDefault);
    CredentialsProvider credentialsProvider = new CredentialsProvider();
    credentialsProvider.setCognitoIdentity(cognitoIdentity);

    S3Default s3Default = new S3Default();
    s3Default.setBucket(sessionModel.getTempBucketName());
    s3Default.setRegion(sessionModel.getRegionName());
    S3TransferUtility s3TransferUtility = new S3TransferUtility();
    s3TransferUtility.setS3Default(s3Default);


    AWSConfig awsConfig = new AWSConfig();
    awsConfig.setVersion("1.0");
    awsConfig.setIdentityManager(identityManager);
    awsConfig.setCredentialsProvider(credentialsProvider);
    awsConfig.setS3TransferUtility(s3TransferUtility);

    return awsConfig;
}

private void setLogin(SessionModel sessionModel) {
    DeveloperAuthenticationProvider developerProvider = new DeveloperAuthenticationProvider(sessionModel);
    CognitoCachingCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider(context, developerProvider, sessionModel.getRegions());
    HashMap<String, String> loginsMap = new HashMap<String, String>();
    loginsMap.put(developerProvider.getProviderName(), developerProvider.getIdentityId());
    credentialsProvider.setLogins(loginsMap);
    credentialsProvider.refresh();
}

}

public class DeveloperAuthenticationProvider extends AWSAbstractCognitoDeveloperIdentityProvider {
    private SessionModel sessionModel;

    public DeveloperAuthenticationProvider(SessionModel sessionModel) {
        super(null, sessionModel.getIdentityPoolId(), sessionModel.getRegions());
        this.sessionModel = sessionModel;
    }

    @Override
    public String getProviderName() {
        return sessionModel.getDeveloperProviderName();
    }

    @Override
    public String refresh() {

        setToken(sessionModel.getToken());

        update(getIdentityId(), sessionModel.getToken());
        return sessionModel.getToken();
    }

    @Override
    public String getIdentityId() {
        return sessionModel.getIdentityId();
    }
}

Which AWS service(s) are affected?

Expected behavior A clear and concise description of what you expected to happen. Assets should be uploaded successfully to S3

Screenshots If applicable, add screenshots to help explain your problem. NA

Environment Information (please complete the following information):

  • AWS Android SDK Version: [e.g. 2.6.25]: 2.45.0
  • Device: [e.g. Pixel XL, Simulator]: Samsung M52 5G (Others device as well)
  • Android Version: [e.g. Nougat 7.1.2]: 11 (on Android 10 & other OS as well)
  • Specific to simulators: [e.g. Yes/No]: No

Additional context Add any other context about the problem here.

girishacme avatar Jul 12 '22 10:07 girishacme

@girishacme Logs are pointing to failure to refresh cognito token, could you please make sure your cognito setup is working as expected.

If yes, then please share your code for SessionModel and also post clear steps to repro this.

sdhuka avatar Jul 13 '22 21:07 sdhuka

@sdhuka After receiving aws token from the server, on success token fetch:

public void onTokenFetch(boolean isSuccessFull, AWSToken awsToken, int errorCode) { if (isSuccessFull) { SessionModel sessionModel = new SessionModel(); sessionModel.setDeveloperProviderName(awsToken.getDeveloperProviderName()); sessionModel.setIdentityId(awsToken.getIdentityId()); sessionModel.setIdentityPoolId(awsToken.getIdentityPoolId()); sessionModel.setRegionName(awsToken.getRegionName()); sessionModel.setRegions(Regions.fromName(awsToken.getRegionName())); sessionModel.setTempBucketName(awsToken.getTempBucketName()); sessionModel.setToken(awsToken.getToken()); startUpload(); } else { handleFailure(errorCode); } }

private void startUpload() {
    try {
        File file = getFileToUpload(id);
        if (file != null && file.exists()) {
            transferUtility = awsUtils.getTransferUtility(customReplicationSession);
            String key = getKey(id);
            TransferObserver observer = transferUtility.upload(key, file);
            id = observer.getId();
            observer.setTransferListener(this);
        } else {
            handleFailure("File not exists");
        }
    } catch (Exception exception) {
        Log.e("Error while uploading assets: " + exception);
    }
}

Code to get transfer utility is already shared above.

This issues starts occurring any time, means there is no as such repro steps for this. Do let me know if you required anything else

girishacme avatar Jul 14 '22 10:07 girishacme

@tylerjroach Any update on this?

girishacme avatar Jul 20 '22 11:07 girishacme

Referencing this previous issue as it is related: https://github.com/aws-amplify/aws-sdk-android/issues/2807

This looks similar to the previous ticket that went unresolved. It appears that the issue could be a bug in Android Studio's Network inspector. The stacktrace posted shows:

com.android.tools.appinspection.network.httpurl.TrackedHttpURLConnection.getErrorStream(TrackedHttpURLConnection.kt:155)

TrackedHttpURLConnection does not exist in the SDK, and is injected by Android Studio's network profiler. Are these crashes only happening when the app is being debugged? If not, it would be helpful to see a crash report that does not lead to Android Studio's TrackedHttpURLConnection.

tylerjroach avatar Jul 22 '22 21:07 tylerjroach

No, many times, I faced this issue when I am not debugging the app, Right now, I don't have any logs for that specific case, but I am sure I faced this issue when I was not debugging the app.

girishacme avatar Jul 25 '22 12:07 girishacme

@girishacme Please follow up if you are able to produce a Stacktrace that does not com from com.android.tools.appinspection. We should be able to track down the issue if a Stacktrace is provided that is not wrapped with the Network Inspector crash.

tylerjroach avatar Aug 04 '22 17:08 tylerjroach

@tylerjroach I will share the logs once this is reproducible without com.android.tools.appinspection

girishacme avatar Aug 12 '22 09:08 girishacme

We will re-open and investigate if we receive logs without appinspection.

tylerjroach avatar Sep 01 '22 16:09 tylerjroach